mirror of
https://github.com/Tzahi12345/YoutubeDL-Material.git
synced 2026-03-25 14:10:57 +03:00
Merge branch 'master' of https://github.com/Tzahi12345/YoutubeDL-Material into categories
This commit is contained in:
@@ -46,7 +46,7 @@
|
||||
<a *ngIf="postsService.config && enableDownloadsManager && (!postsService.config.Advanced.multi_user_mode || (postsService.isLoggedIn && postsService.permissions.includes('downloads_manager')))" mat-list-item (click)="postsService.sidepanel_mode === 'over' ? sidenav.close() : null" routerLink='/downloads'><ng-container i18n="Navigation menu Downloads Page title">Downloads</ng-container></a>
|
||||
<ng-container *ngIf="postsService.config && allowSubscriptions && postsService.subscriptions && (!postsService.config.Advanced.multi_user_mode || (postsService.isLoggedIn && postsService.permissions.includes('subscriptions')))">
|
||||
<mat-divider></mat-divider>
|
||||
<a *ngFor="let subscription of postsService.subscriptions" mat-list-item (click)="postsService.sidepanel_mode === 'over' ? sidenav.close() : null" [routerLink]="['/subscription', { id: subscription.id }]"><ngx-avatar [style.margin-right]="'10px'" size="32" [name]="subscription.name"></ngx-avatar><ng-container i18n="Navigation menu Downloads Page title">{{subscription.name}}</ng-container></a>
|
||||
<a *ngFor="let subscription of postsService.subscriptions" mat-list-item (click)="postsService.sidepanel_mode === 'over' ? sidenav.close() : null" [routerLink]="['/subscription', { id: subscription.id }]"><ngx-avatar [style.margin-right]="'10px'" size="32" [name]="subscription.name"></ngx-avatar>{{subscription.name}}</a>
|
||||
</ng-container>
|
||||
</mat-nav-list>
|
||||
</mat-sidenav>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div *ngFor="let playlist of playlists; let i = index" class="mb-2 mt-2" [ngClass]="[ postsService.card_size === 'small' ? 'col-2 small-col' : '', postsService.card_size === 'medium' ? 'col-6 col-lg-4 medium-col' : '', postsService.card_size === 'large' ? 'col-12 large-col' : '' ]">
|
||||
<app-unified-file-card [index]="i" [card_size]="postsService.card_size" (goToFile)="goToPlaylist($event)" [file_obj]="playlist" [is_playlist]="true" (editPlaylist)="editPlaylistDialog($event)" (deleteFile)="deletePlaylist($event)" [loading]="false"></app-unified-file-card>
|
||||
<app-unified-file-card [index]="i" [card_size]="postsService.card_size" [locale]="postsService.locale" (goToFile)="goToPlaylist($event)" [file_obj]="playlist" [is_playlist]="true" (editPlaylist)="editPlaylistDialog($event)" (deleteFile)="deletePlaylist($event)" [loading]="false"></app-unified-file-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -50,8 +50,8 @@ export class CustomPlaylistsComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
goToPlaylist(event_info) {
|
||||
const playlist = event_info.file;
|
||||
goToPlaylist(info_obj) {
|
||||
const playlist = info_obj.file;
|
||||
const playlistID = playlist.id;
|
||||
const type = playlist.type;
|
||||
|
||||
@@ -83,7 +83,7 @@ export class CustomPlaylistsComponent implements OnInit {
|
||||
const playlist = args.file;
|
||||
const index = args.index;
|
||||
const playlistID = playlist.id;
|
||||
this.postsService.removePlaylist(playlistID, 'audio').subscribe(res => {
|
||||
this.postsService.removePlaylist(playlistID, playlist.type).subscribe(res => {
|
||||
if (res['success']) {
|
||||
this.playlists.splice(index, 1);
|
||||
this.postsService.openSnackBar('Playlist successfully removed.', '');
|
||||
|
||||
@@ -32,12 +32,12 @@
|
||||
<div class="row justify-content-center">
|
||||
<ng-container *ngIf="normal_files_received">
|
||||
<div *ngFor="let file of filtered_files; let i = index" class="mb-2 mt-2 d-flex justify-content-center" [ngClass]="[ postsService.card_size === 'small' ? 'col-2 small-col' : '', postsService.card_size === 'medium' ? 'col-6 col-lg-4 medium-col' : '', postsService.card_size === 'large' ? 'col-12 large-col' : '' ]">
|
||||
<app-unified-file-card [index]="i" [card_size]="postsService.card_size" (goToFile)="goToFile($event)" (goToSubscription)="goToSubscription($event)" [file_obj]="file" [use_youtubedl_archive]="postsService.config['Downloader']['use_youtubedl_archive']" [loading]="false" (deleteFile)="deleteFile($event)"></app-unified-file-card>
|
||||
<app-unified-file-card [index]="i" [card_size]="postsService.card_size" [locale]="postsService.locale" (goToFile)="goToFile($event)" (goToSubscription)="goToSubscription($event)" [file_obj]="file" [use_youtubedl_archive]="postsService.config['Downloader']['use_youtubedl_archive']" [loading]="false" (deleteFile)="deleteFile($event)"></app-unified-file-card>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!normal_files_received && loading_files && loading_files.length > 0">
|
||||
<div *ngFor="let file of loading_files; let i = index" class="mb-2 mt-2 d-flex justify-content-center" [ngClass]="[ postsService.card_size === 'small' ? 'col-2 small-col' : '', postsService.card_size === 'medium' ? 'col-6 col-lg-4 medium-col' : '', postsService.card_size === 'large' ? 'col-12 large-col' : '' ]">
|
||||
<app-unified-file-card [index]="i" [card_size]="postsService.card_size" [loading]="true" [theme]="postsService.theme"></app-unified-file-card>
|
||||
<app-unified-file-card [index]="i" [card_size]="postsService.card_size" [locale]="postsService.locale" [loading]="true" [theme]="postsService.theme"></app-unified-file-card>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,19 @@
|
||||
<div (mouseover)="elevated=true" (mouseout)="elevated=false" style="position: relative; width: fit-content;">
|
||||
<div *ngIf="!loading" class="download-time"><mat-icon class="audio-video-icon">{{(file_obj.type === 'audio' || file_obj.isAudio) ? 'audiotrack' : 'movie'}}</mat-icon> {{file_obj.registered | date:'shortDate'}}</div>
|
||||
<div (mouseover)="elevated=true" (mouseout)="elevated=false" (contextmenu)="onRightClick($event)" style="position: relative; width: fit-content;">
|
||||
<div *ngIf="!loading" class="download-time"><mat-icon class="audio-video-icon">{{(file_obj.type === 'audio' || file_obj.isAudio) ? 'audiotrack' : 'movie'}}</mat-icon> {{file_obj.registered | date:'shortDate' : undefined : locale.ngID}}</div>
|
||||
<div *ngIf="loading" class="download-time" style="width: 75%; margin-top: 5px;"><content-loader [primaryColor]="theme.ghost_primary" [secondaryColor]="theme.ghost_secondary" width="250" height="30"><svg:rect x="0" y="0" rx="3" ry="3" width="250" height="30" /></content-loader></div>
|
||||
<!-- The context menu trigger must be kept above the "more info" menu -->
|
||||
<div style="visibility: hidden; position: fixed"
|
||||
[style.left]="contextMenuPosition.x"
|
||||
[style.top]="contextMenuPosition.y"
|
||||
[matMenuTriggerFor]="context_menu">
|
||||
</div>
|
||||
<button [disabled]="loading" [matMenuTriggerFor]="action_menu" class="menuButton" mat-icon-button><mat-icon>more_vert</mat-icon></button>
|
||||
<mat-menu #context_menu>
|
||||
<ng-container *ngIf="!loading">
|
||||
<button (click)="navigateToFile($event)" mat-menu-item><mat-icon>open_in_browser</mat-icon><ng-container i18n="Open file button">Open file</ng-container></button>
|
||||
<button (click)="navigateToFile({ctrlKey: true})" mat-menu-item><mat-icon>open_in_new</mat-icon><ng-container i18n="Open file in new tab">Open file in new tab</ng-container></button>
|
||||
</ng-container>
|
||||
</mat-menu>
|
||||
<mat-menu #action_menu="matMenu">
|
||||
<ng-container *ngIf="!is_playlist && !loading">
|
||||
<button (click)="openFileInfoDialog()" mat-menu-item><mat-icon>info</mat-icon><ng-container i18n="Video info button">Info</ng-container></button>
|
||||
|
||||
@@ -1,7 +1,22 @@
|
||||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { Component, OnInit, Input, Output, EventEmitter, ViewChild } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { VideoInfoDialogComponent } from 'app/dialogs/video-info-dialog/video-info-dialog.component';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { MatMenuTrigger } from '@angular/material/menu';
|
||||
import { registerLocaleData } from '@angular/common';
|
||||
import localeGB from '@angular/common/locales/en-GB';
|
||||
import localeFR from '@angular/common/locales/fr';
|
||||
import localeES from '@angular/common/locales/es';
|
||||
import localeDE from '@angular/common/locales/de';
|
||||
import localeZH from '@angular/common/locales/zh';
|
||||
import localeNB from '@angular/common/locales/nb';
|
||||
|
||||
registerLocaleData(localeGB);
|
||||
registerLocaleData(localeFR);
|
||||
registerLocaleData(localeES);
|
||||
registerLocaleData(localeDE);
|
||||
registerLocaleData(localeZH);
|
||||
registerLocaleData(localeNB);
|
||||
|
||||
@Component({
|
||||
selector: 'app-unified-file-card',
|
||||
@@ -28,10 +43,15 @@ export class UnifiedFileCardComponent implements OnInit {
|
||||
@Input() use_youtubedl_archive = false;
|
||||
@Input() is_playlist = false;
|
||||
@Input() index: number;
|
||||
@Input() locale = null;
|
||||
@Output() goToFile = new EventEmitter<any>();
|
||||
@Output() goToSubscription = new EventEmitter<any>();
|
||||
@Output() deleteFile = new EventEmitter<any>();
|
||||
@Output() editPlaylist = new EventEmitter<any>();
|
||||
|
||||
|
||||
@ViewChild(MatMenuTrigger) contextMenu: MatMenuTrigger;
|
||||
contextMenuPosition = { x: '0px', y: '0px' };
|
||||
|
||||
/*
|
||||
Planned sizes:
|
||||
@@ -87,6 +107,15 @@ export class UnifiedFileCardComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
onRightClick(event) {
|
||||
event.preventDefault();
|
||||
this.contextMenuPosition.x = event.clientX + 'px';
|
||||
this.contextMenuPosition.y = event.clientY + 'px';
|
||||
this.contextMenu.menuData = { 'item': {id: 1, name: 'hi'} };
|
||||
this.contextMenu.menu.focusFirstItem('mouse');
|
||||
this.contextMenu.openMenu();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function fancyTimeFormat(time) {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</ng-template>
|
||||
</ngx-file-drop>
|
||||
<div style="margin-top: 15px;">
|
||||
<p style="font-size: 14px;" i18n="Cookies upload warning">NOTE: Uploading new cookies will overrride your previous cookies. Also note that cookies are instance-wide, not per-user.</p>
|
||||
<p style="font-size: 14px;" i18n="Cookies upload warning">NOTE: Uploading new cookies will override your previous cookies. Also note that cookies are instance-wide, not per-user.</p>
|
||||
</div>
|
||||
<div style="margin-top: 10px;">
|
||||
<table class="table">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<h4 mat-dialog-title i18n="Edit subscription dialog title">Editing {{sub.name}}</h4>
|
||||
<h4 mat-dialog-title i18n="Edit subscription dialog title prefix">Editing</h4> {{sub.name}}
|
||||
|
||||
<mat-dialog-content>
|
||||
<div class="container-fluid">
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</mat-button-toggle-group>
|
||||
|
||||
<div class="add-content-button">
|
||||
<button [disabled]="available_files.length === 0" mat-stroked-button [matMenuTriggerFor]="menu">Add more content</button>
|
||||
<button [disabled]="available_files.length === 0" mat-stroked-button [matMenuTriggerFor]="menu"><ng-container i18n="Add more content">Add more content</ng-container></button>
|
||||
</div>
|
||||
<mat-menu #menu="matMenu">
|
||||
<button *ngFor="let file of available_files" (click)="addContent(file)" mat-menu-item>{{file}}</button>
|
||||
@@ -24,5 +24,5 @@
|
||||
|
||||
<mat-dialog-actions>
|
||||
<!-- Save -->
|
||||
<button [disabled]="!playlistChanged()" (click)="updatePlaylist()" [disabled]="playlistChanged()" mat-raised-button color="accent">Save</button>
|
||||
<button [disabled]="!playlistChanged()" (click)="updatePlaylist()" [disabled]="playlistChanged()" mat-raised-button color="accent"><ng-container i18n="Save">Save</ng-container></button>
|
||||
</mat-dialog-actions>
|
||||
@@ -181,10 +181,12 @@
|
||||
|
||||
</ng-template>
|
||||
|
||||
<app-recent-videos></app-recent-videos>
|
||||
<br/>
|
||||
<h4 style="text-align: center">Custom playlists</h4>
|
||||
<app-custom-playlists></app-custom-playlists>
|
||||
<ng-container *ngIf="cachedFileManagerEnabled || fileManagerEnabled">
|
||||
<app-recent-videos></app-recent-videos>
|
||||
<br/>
|
||||
<h4 style="text-align: center">Custom playlists</h4>
|
||||
<app-custom-playlists></app-custom-playlists>
|
||||
</ng-container>
|
||||
|
||||
<!--<div style="margin: 20px" *ngIf="fileManagerEnabled && (!postsService.isLoggedIn || postsService.permissions.includes('filemanager'))">
|
||||
<mat-accordion>
|
||||
|
||||
@@ -82,8 +82,9 @@ export class MainComponent implements OnInit {
|
||||
useDefaultDownloadingAgent = true;
|
||||
customDownloadingAgent = null;
|
||||
|
||||
// formats cache
|
||||
// cache
|
||||
cachedAvailableFormats = {};
|
||||
cachedFileManagerEnabled = localStorage.getItem('cached_filemanager_enabled') === 'true';
|
||||
|
||||
// youtube api
|
||||
youtubeSearchEnabled = false;
|
||||
@@ -232,7 +233,8 @@ export class MainComponent implements OnInit {
|
||||
|
||||
async loadConfig() {
|
||||
// loading config
|
||||
this.fileManagerEnabled = this.postsService.config['Extra']['file_manager_enabled'];
|
||||
this.fileManagerEnabled = this.postsService.config['Extra']['file_manager_enabled']
|
||||
&& (!this.postsService.isLoggedIn || this.postsService.permissions.includes('filemanager'));
|
||||
this.downloadOnlyMode = this.postsService.config['Extra']['download_only_mode'];
|
||||
this.allowMultiDownloadMode = this.postsService.config['Extra']['allow_multi_download_mode'];
|
||||
this.audioFolderPath = this.postsService.config['Downloader']['path-audio'];
|
||||
@@ -261,6 +263,10 @@ export class MainComponent implements OnInit {
|
||||
}
|
||||
|
||||
// set final cache items
|
||||
|
||||
localStorage.setItem('cached_filemanager_enabled', this.fileManagerEnabled.toString());
|
||||
this.cachedFileManagerEnabled = this.fileManagerEnabled;
|
||||
|
||||
if (this.allowAdvancedDownload) {
|
||||
if (localStorage.getItem('customArgsEnabled') !== null) {
|
||||
this.customArgsEnabled = localStorage.getItem('customArgsEnabled') === 'true';
|
||||
|
||||
@@ -341,7 +341,8 @@ export class PlayerComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
|
||||
const zipName = fileNames[0].split(' ')[0] + fileNames[1].split(' ')[0];
|
||||
this.downloading = true;
|
||||
this.postsService.downloadFileFromServer(fileNames, this.type, zipName).subscribe(res => {
|
||||
this.postsService.downloadFileFromServer(fileNames, this.type, zipName, null, null, null, null,
|
||||
!this.uuid ? this.postsService.user.uid : this.uuid, this.id).subscribe(res => {
|
||||
this.downloading = false;
|
||||
const blob: Blob = res;
|
||||
saveAs(blob, zipName + '.zip');
|
||||
|
||||
@@ -11,6 +11,7 @@ import { BehaviorSubject } from 'rxjs';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import * as Fingerprint2 from 'fingerprintjs2';
|
||||
import { isoLangs } from './settings/locales_list';
|
||||
|
||||
@Injectable()
|
||||
export class PostsService implements CanActivate {
|
||||
@@ -54,6 +55,7 @@ export class PostsService implements CanActivate {
|
||||
subscriptions = null;
|
||||
categories = null;
|
||||
sidenav = null;
|
||||
locale = isoLangs['en'];
|
||||
|
||||
constructor(private http: HttpClient, private router: Router, @Inject(DOCUMENT) private document: Document,
|
||||
public snackBar: MatSnackBar) {
|
||||
@@ -115,6 +117,17 @@ export class PostsService implements CanActivate {
|
||||
if (localStorage.getItem('card_size')) {
|
||||
this.card_size = localStorage.getItem('card_size');
|
||||
}
|
||||
|
||||
// localization
|
||||
const locale = localStorage.getItem('locale');
|
||||
if (!locale) {
|
||||
localStorage.setItem('locale', 'en');
|
||||
}
|
||||
|
||||
if (isoLangs[locale]) {
|
||||
this.locale = isoLangs[locale];
|
||||
}
|
||||
|
||||
}
|
||||
canActivate(route, state): Promise<boolean> {
|
||||
return new Promise(resolve => {
|
||||
@@ -220,7 +233,7 @@ export class PostsService implements CanActivate {
|
||||
}
|
||||
|
||||
downloadFileFromServer(fileName, type, outputName = null, fullPathProvided = null, subscriptionName = null, subPlaylist = null,
|
||||
uid = null, uuid = null) {
|
||||
uid = null, uuid = null, id = null) {
|
||||
return this.http.post(this.path + 'downloadFile', {fileNames: fileName,
|
||||
type: type,
|
||||
zip_mode: Array.isArray(fileName),
|
||||
@@ -229,7 +242,8 @@ export class PostsService implements CanActivate {
|
||||
subscriptionName: subscriptionName,
|
||||
subPlaylist: subPlaylist,
|
||||
uuid: uuid,
|
||||
uid: uid
|
||||
uid: uid,
|
||||
id: id
|
||||
},
|
||||
{responseType: 'blob', params: this.httpOptions.params});
|
||||
}
|
||||
|
||||
@@ -122,7 +122,8 @@ export const isoLangs = {
|
||||
},
|
||||
'zh': {
|
||||
'name': 'Chinese',
|
||||
'nativeName': '中文 (Zhōngwén), 汉语, 漢語'
|
||||
'nativeName': '中文 (Zhōngwén), 汉语, 漢語',
|
||||
'ngID': 'zh'
|
||||
},
|
||||
'cv': {
|
||||
'name': 'Chuvash',
|
||||
@@ -162,8 +163,14 @@ export const isoLangs = {
|
||||
},
|
||||
'en': {
|
||||
'name': 'English',
|
||||
'nativeName': 'English'
|
||||
'nativeName': 'English',
|
||||
'ngID': 'en-US'
|
||||
},
|
||||
'en-GB': {
|
||||
'name': 'British English',
|
||||
'nativeName': 'British English',
|
||||
'ngID': 'en-GB'
|
||||
},
|
||||
'eo': {
|
||||
'name': 'Esperanto',
|
||||
'nativeName': 'Esperanto'
|
||||
@@ -190,7 +197,8 @@ export const isoLangs = {
|
||||
},
|
||||
'fr': {
|
||||
'name': 'French',
|
||||
'nativeName': 'français, langue française'
|
||||
'nativeName': 'français',
|
||||
'ngID': 'fr'
|
||||
},
|
||||
'ff': {
|
||||
'name': 'Fula; Fulah; Pulaar; Pular',
|
||||
@@ -206,7 +214,8 @@ export const isoLangs = {
|
||||
},
|
||||
'de': {
|
||||
'name': 'German',
|
||||
'nativeName': 'Deutsch'
|
||||
'nativeName': 'Deutsch',
|
||||
'ngID': 'de'
|
||||
},
|
||||
'el': {
|
||||
'name': 'Greek, Modern',
|
||||
@@ -438,7 +447,8 @@ export const isoLangs = {
|
||||
},
|
||||
'nb': {
|
||||
'name': 'Norwegian Bokmål',
|
||||
'nativeName': 'Norsk bokmål'
|
||||
'nativeName': 'Norsk bokmål',
|
||||
'ngID': 'nb'
|
||||
},
|
||||
'nd': {
|
||||
'name': 'North Ndebele',
|
||||
@@ -594,7 +604,8 @@ export const isoLangs = {
|
||||
},
|
||||
'es': {
|
||||
'name': 'Spanish; Castilian',
|
||||
'nativeName': 'español'
|
||||
'nativeName': 'español',
|
||||
'ngID': 'es'
|
||||
},
|
||||
'su': {
|
||||
'name': 'Sundanese',
|
||||
|
||||
@@ -276,7 +276,7 @@
|
||||
</div>
|
||||
<div class="col-12 mt-2 mb-1">
|
||||
<mat-form-field>
|
||||
<mat-label><ng-container i18n="Logger level select label">Select a logger level</ng-container></mat-label>
|
||||
<mat-label><ng-container i18n="Log Level label">Log Level</ng-container></mat-label>
|
||||
<mat-select color="accent" [(ngModel)]="new_config['Advanced']['logger_level']">
|
||||
<mat-option value="debug">Debug</mat-option>
|
||||
<mat-option value="verbose">Verbose</mat-option>
|
||||
|
||||
@@ -20,7 +20,7 @@ import { EditCategoryDialogComponent } from 'app/dialogs/edit-category-dialog/ed
|
||||
})
|
||||
export class SettingsComponent implements OnInit {
|
||||
all_locales = isoLangs;
|
||||
supported_locales = ['en', 'es', 'de'];
|
||||
supported_locales = ['en', 'es', 'de', 'fr', 'zh', 'nb', 'en-GB'];
|
||||
initialLocale = localStorage.getItem('locale');
|
||||
|
||||
initial_config = null;
|
||||
|
||||
@@ -108,7 +108,7 @@ export class SubscriptionComponent implements OnInit {
|
||||
} else {
|
||||
this.router.navigate(['/player', {fileNames: name,
|
||||
type: this.subscription.type ? this.subscription.type : 'video', subscriptionName: this.subscription.name,
|
||||
subPlaylist: this.subscription.isPlaylist, uuid: this.postsService.user ? this.postsService.user.uid : null}]);
|
||||
subPlaylist: this.subscription.isPlaylist}]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user