mirror of
https://github.com/alexta69/metube.git
synced 2026-06-13 16:40:05 +00:00
Merge branch 'pr-977'
This commit is contained in:
+1
-1
@@ -5,7 +5,7 @@
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"build:watch": "ng build --watch",
|
||||
"build:watch": "ng build --watch --configuration development",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint"
|
||||
},
|
||||
|
||||
+49
-63
@@ -279,13 +279,12 @@
|
||||
</div>
|
||||
<div class="col-12 col-md-6 col-lg-3">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Format</span>
|
||||
<span class="input-group-text help-title" ngbPopover="Subtitle output format for captions mode." triggers="click" autoClose="outside" container="body">Format</span>
|
||||
<select class="form-select"
|
||||
name="format"
|
||||
[(ngModel)]="format"
|
||||
(change)="formatChanged()"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
ngbTooltip="Subtitle output format for captions mode">
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading">
|
||||
@for (f of formatOptions; track f.id) {
|
||||
<option [ngValue]="f.id">{{ f.text }}</option>
|
||||
}
|
||||
@@ -294,7 +293,7 @@
|
||||
</div>
|
||||
<div class="col-12 col-md-6 col-lg-3">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Language</span>
|
||||
<span class="input-group-text help-title" ngbPopover="Subtitle language (you can type any language code)." triggers="click" autoClose="outside" container="body">Language</span>
|
||||
<input class="form-control"
|
||||
type="text"
|
||||
list="subtitleLanguageOptions"
|
||||
@@ -302,8 +301,7 @@
|
||||
[(ngModel)]="subtitleLanguage"
|
||||
(change)="subtitleLanguageChanged()"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
placeholder="e.g. en, es, zh-Hans"
|
||||
ngbTooltip="Subtitle language (you can type any language code)">
|
||||
placeholder="e.g. en, es, zh-Hans">
|
||||
<datalist id="subtitleLanguageOptions">
|
||||
@for (lang of subtitleLanguages; track lang.id) {
|
||||
<option [value]="lang.id">{{ lang.text }}</option>
|
||||
@@ -313,13 +311,12 @@
|
||||
</div>
|
||||
<div class="col-12 col-md-6 col-lg-3">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Subtitle Source</span>
|
||||
<span class="input-group-text help-title" ngbPopover="Choose manual, auto, or fallback preference for captions mode." triggers="click" autoClose="outside" container="body">Subtitle Source</span>
|
||||
<select class="form-select"
|
||||
name="subtitleMode"
|
||||
[(ngModel)]="subtitleMode"
|
||||
(change)="subtitleModeChanged()"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
ngbTooltip="Choose manual, auto, or fallback preference for captions mode">
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading">
|
||||
@for (mode of subtitleModes; track mode.id) {
|
||||
<option [ngValue]="mode.id">{{ mode.text }}</option>
|
||||
}
|
||||
@@ -375,34 +372,29 @@
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Download Folder</span>
|
||||
@if (customDirs$ | async; as customDirs) {
|
||||
<ng-select [items]="customDirs"
|
||||
<span class="input-group-text help-title" ngbPopover="Type to filter existing folders, or enter a new folder name." triggers="click" autoClose="outside" container="body">Download Folder</span>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
placeholder="Default"
|
||||
[addTag]="allowCustomDir.bind(this)"
|
||||
addTagText="Create directory"
|
||||
bindLabel="folder"
|
||||
name="folder"
|
||||
[(ngModel)]="folder"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
[virtualScroll]="true"
|
||||
[clearable]="true"
|
||||
[loading]="downloads.loading"
|
||||
[searchable]="true"
|
||||
[closeOnSelect]="true"
|
||||
ngbTooltip="Choose where to save downloads. Type to create a new folder." />
|
||||
}
|
||||
[ngbTypeahead]="searchFolder"
|
||||
[editable]="!!downloads.configuration['CREATE_CUSTOM_DIRS']"
|
||||
(focus)="folderFocus$.next($any($event.target).value)"
|
||||
(click)="folderClick$.next($any($event.target).value)"
|
||||
#folderTypeahead="ngbTypeahead"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Custom Name Prefix</span>
|
||||
<span class="input-group-text help-title" ngbPopover="Add a prefix to downloaded filenames." triggers="click" autoClose="outside" container="body">Custom Name Prefix</span>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
placeholder="Default"
|
||||
name="customNamePrefix"
|
||||
[(ngModel)]="customNamePrefix"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
ngbTooltip="Add a prefix to downloaded filenames">
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
@@ -411,18 +403,16 @@
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkbox-split-chapters"
|
||||
name="splitByChapters" [(ngModel)]="splitByChapters" (change)="splitByChaptersChanged()"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
ngbTooltip="Split video into separate files by chapters">
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading">
|
||||
<label class="form-check-label" for="checkbox-split-chapters">Split by chapters</label>
|
||||
</div>
|
||||
</div>
|
||||
@if (splitByChapters) {
|
||||
<div class="col">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Template</span>
|
||||
<span class="input-group-text help-title" ngbPopover="Output template for chapter files." triggers="click" autoClose="outside" container="body">Template</span>
|
||||
<input type="text" class="form-control" name="chapterTemplate" [(ngModel)]="chapterTemplate"
|
||||
(change)="chapterTemplateChanged()" [disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
ngbTooltip="Output template for chapter files">
|
||||
(change)="chapterTemplateChanged()" [disabled]="addInProgress || subscribeInProgress || downloads.loading">
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -431,28 +421,26 @@
|
||||
@if (downloadType === 'video' || downloadType === 'audio') {
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Clip start</span>
|
||||
<span class="input-group-text help-title" ngbPopover="Optional start time (seconds, M:SS, or H:MM:SS). Blank = from start or YouTube &t= in URL." triggers="click" autoClose="outside" container="body">Clip start</span>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="clipStart"
|
||||
[(ngModel)]="clipStart"
|
||||
(change)="clipStartChanged()"
|
||||
placeholder="e.g. 2:26"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
ngbTooltip="Optional start time (seconds, M:SS, or H:MM:SS). Blank = from start or YouTube &t= in URL.">
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Clip end</span>
|
||||
<span class="input-group-text help-title" ngbPopover="Optional end time. Blank = until end of media." triggers="click" autoClose="outside" container="body">Clip end</span>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="clipEnd"
|
||||
[(ngModel)]="clipEnd"
|
||||
(change)="clipEndChanged()"
|
||||
placeholder="e.g. 3:24"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
ngbTooltip="Optional end time. Blank = until end of media.">
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading">
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -463,13 +451,12 @@
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Auto Start</span>
|
||||
<span class="input-group-text help-title" ngbPopover="Automatically start downloads when added." triggers="click" autoClose="outside" container="body">Auto Start</span>
|
||||
<select class="form-select"
|
||||
name="autoStart"
|
||||
[(ngModel)]="autoStart"
|
||||
(change)="autoStartChanged()"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
ngbTooltip="Automatically start downloads when added">
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading">
|
||||
<option [ngValue]="true">Yes</option>
|
||||
<option [ngValue]="false">No</option>
|
||||
</select>
|
||||
@@ -477,7 +464,7 @@
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Items Limit</span>
|
||||
<span class="input-group-text help-title" ngbPopover="Maximum number of items to download from a playlist or channel (0 = no limit)." triggers="click" autoClose="outside" container="body">Items Limit</span>
|
||||
<input type="number"
|
||||
min="0"
|
||||
class="form-control"
|
||||
@@ -485,13 +472,12 @@
|
||||
name="playlistItemLimit"
|
||||
(keydown)="isNumber($event)"
|
||||
[(ngModel)]="playlistItemLimit"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
ngbTooltip="Maximum number of items to download from a playlist or channel (0 = no limit)">
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Subscription Check (min)</span>
|
||||
<span class="input-group-text help-title" ngbPopover="How often to poll subscriptions for new videos." triggers="click" autoClose="outside" container="body">Subscription Check (min)</span>
|
||||
<input type="number"
|
||||
min="1"
|
||||
class="form-control"
|
||||
@@ -499,29 +485,33 @@
|
||||
(keydown)="isNumber($event)"
|
||||
[(ngModel)]="checkIntervalMinutes"
|
||||
(ngModelChange)="checkIntervalChanged()"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
ngbTooltip="How often to poll subscriptions for new videos">
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Subscription Title Filter</span>
|
||||
<span class="input-group-text help-title" ngbPopover="In subscriptions, only titles matching this Python-style regex are queued. Empty = all. Case-sensitive; use (?i) in the pattern for case-insensitive." triggers="click" autoClose="outside" container="body">Subscription Title Filter</span>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="titleRegex"
|
||||
[(ngModel)]="titleRegex"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
placeholder="Optional regex"
|
||||
ngbTooltip="In subscriptions, only titles matching this Python-style regex are queued. Empty = all. Case-sensitive; use (?i) in the pattern for case-insensitive.">
|
||||
placeholder="Optional regex">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkbox-skip-subscriber-only"
|
||||
name="skipSubscriberOnly" [(ngModel)]="skipSubscriberOnly"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
ngbTooltip="When enabled, subscription checks skip videos marked members-only by yt-dlp (channel Join). Ignored for one-off downloads." />
|
||||
<label class="form-check-label" for="checkbox-skip-subscriber-only">Skip members-only subscription videos</label>
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading" />
|
||||
<label class="form-check-label" for="checkbox-skip-subscriber-only">
|
||||
<span class="help-title" tabindex="0" role="button"
|
||||
ngbPopover="When enabled, subscription checks skip videos marked members-only by yt-dlp (channel Join). Ignored for one-off downloads."
|
||||
triggers="click" autoClose="outside" container="body"
|
||||
(click)="$event.preventDefault(); $event.stopPropagation()"
|
||||
(keydown.enter)="$event.preventDefault(); $event.stopPropagation()"
|
||||
(keydown.space)="$event.preventDefault(); $event.stopPropagation()">Skip members-only subscription videos</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -531,7 +521,7 @@
|
||||
<div class="row g-3">
|
||||
<div class="col-12" [class.col-md-6]="allowYtdlOptionsOverrides()">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Option Presets</span>
|
||||
<span class="input-group-text help-title" ngbPopover="Choose one or more yt-dlp option presets configured on the server (applied in order)." triggers="click" autoClose="outside" container="body">Option Presets</span>
|
||||
<ng-select
|
||||
class="flex-grow-1"
|
||||
name="ytdlOptionsPresets"
|
||||
@@ -541,22 +531,20 @@
|
||||
placeholder="Default"
|
||||
[(ngModel)]="ytdlOptionsPresets"
|
||||
(ngModelChange)="ytdlOptionsPresetsChanged()"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
ngbTooltip="Choose one or more yt-dlp option presets configured on the server (applied in order)" />
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading" />
|
||||
</div>
|
||||
</div>
|
||||
@if (allowYtdlOptionsOverrides()) {
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Custom yt-dlp Options</span>
|
||||
<span class="input-group-text help-title" ngbPopover="Optional per-download yt-dlp overrides as a JSON object." triggers="click" autoClose="outside" container="body">Custom yt-dlp Options</span>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
placeholder='e.g. {"writesubtitles": true}'
|
||||
name="ytdlOptionsOverrides"
|
||||
[(ngModel)]="ytdlOptionsOverrides"
|
||||
(change)="ytdlOptionsOverridesChanged()"
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading"
|
||||
ngbTooltip="Optional per-download yt-dlp overrides as a JSON object">
|
||||
[disabled]="addInProgress || subscribeInProgress || downloads.loading">
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -566,7 +554,7 @@
|
||||
<div class="settings-section-label">Tools</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<div class="action-group-label">Cookies</div>
|
||||
<div class="action-group-label help-title" ngbPopover="Upload a cookies.txt file from your browser to authenticate restricted or private downloads." triggers="click" autoClose="outside" container="body">Cookies</div>
|
||||
<input type="file" id="cookie-upload" class="d-none" accept=".txt"
|
||||
(change)="onCookieFileSelect($event)"
|
||||
[disabled]="cookieUploadInProgress || addInProgress">
|
||||
@@ -574,8 +562,7 @@
|
||||
<label class="btn mb-0"
|
||||
[class]="hasCookies ? 'btn cookie-active-btn mb-0' : 'btn cookie-btn mb-0'"
|
||||
[class.disabled]="cookieUploadInProgress || addInProgress"
|
||||
for="cookie-upload"
|
||||
ngbTooltip="Upload a cookies.txt file for authenticated downloads">
|
||||
for="cookie-upload">
|
||||
@if (cookieUploadInProgress) {
|
||||
<span class="spinner-border spinner-border-sm me-2" role="status"></span>
|
||||
} @else {
|
||||
@@ -939,8 +926,7 @@
|
||||
</th>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">URL</th>
|
||||
<th scope="col" class="text-nowrap"
|
||||
ngbTooltip="Subscriptions only — which new video titles to queue when this feed is checked. Does not affect manual downloads.">Sub. title filter</th>
|
||||
<th scope="col" class="text-nowrap"><span class="help-title" ngbPopover="Subscriptions only — which new video titles to queue when this feed is checked. Does not affect manual downloads." triggers="click" autoClose="outside" container="body">Sub. title filter</span></th>
|
||||
<th scope="col" class="text-nowrap">Interval (min)</th>
|
||||
<th scope="col" class="text-nowrap">Last checked</th>
|
||||
<th scope="col">Status</th>
|
||||
|
||||
@@ -201,6 +201,14 @@ main
|
||||
color: var(--bs-secondary-color)
|
||||
margin-bottom: 0.4rem
|
||||
|
||||
.help-title
|
||||
text-decoration: underline dotted
|
||||
text-underline-offset: 0.2em
|
||||
cursor: help
|
||||
|
||||
&:focus
|
||||
outline: none
|
||||
|
||||
.cookie-status
|
||||
font-size: 0.8rem
|
||||
margin-top: 0.35rem
|
||||
|
||||
+27
-35
@@ -1,12 +1,12 @@
|
||||
import { AsyncPipe, DatePipe, KeyValuePipe, NgTemplateOutlet } from '@angular/common';
|
||||
import { DatePipe, KeyValuePipe, NgTemplateOutlet } from '@angular/common';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, ElementRef, viewChild, inject, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Observable, Subject, Subscription, from, map, distinctUntilChanged, finalize, mergeMap, takeUntil, tap } from 'rxjs';
|
||||
import { Observable, OperatorFunction, Subject, Subscription, from, map, merge, debounceTime, distinctUntilChanged, filter, finalize, mergeMap, takeUntil, tap } from 'rxjs';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { NgSelectModule } from '@ng-select/ng-select';
|
||||
import { NgbModule, NgbTypeahead } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { NgSelectModule } from '@ng-select/ng-select';
|
||||
import { faTrashAlt, faCheckCircle, faTimesCircle, faRedoAlt, faSun, faMoon, faCheck, faCircleHalfStroke, faDownload, faExternalLinkAlt, faFileImport, faFileExport, faCopy, faClock, faTachometerAlt, faSortAmountDown, faSortAmountUp, faChevronRight, faChevronDown, faUpload, faPause, faPlay, faShareNodes } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faGithub } from '@fortawesome/free-brands-svg-icons';
|
||||
import { CookieService } from 'ngx-cookie-service';
|
||||
@@ -40,7 +40,6 @@ import { SelectAllCheckboxComponent, ItemCheckboxComponent } from './components/
|
||||
FormsModule,
|
||||
NgTemplateOutlet,
|
||||
KeyValuePipe,
|
||||
AsyncPipe,
|
||||
DatePipe,
|
||||
FontAwesomeModule,
|
||||
NgbModule,
|
||||
@@ -105,8 +104,10 @@ export class App implements AfterViewInit, OnInit, OnDestroy {
|
||||
cookieUploadInProgress = false;
|
||||
themes: Theme[] = Themes;
|
||||
activeTheme: Theme | undefined;
|
||||
customDirs$!: Observable<string[]>;
|
||||
showBatchPanel = false;
|
||||
readonly folderTypeahead = viewChild<NgbTypeahead>('folderTypeahead');
|
||||
folderFocus$ = new Subject<string>();
|
||||
folderClick$ = new Subject<string>();
|
||||
showBatchPanel = false;
|
||||
batchImportModalOpen = false;
|
||||
batchImportText = '';
|
||||
batchImportStatus = '';
|
||||
@@ -309,7 +310,6 @@ export class App implements AfterViewInit, OnInit, OnDestroy {
|
||||
this.getConfiguration();
|
||||
this.getYtdlOptionsUpdateTime();
|
||||
this.getYtdlOptionPresets();
|
||||
this.customDirs$ = this.getMatchingCustomDir();
|
||||
this.setTheme(this.activeTheme!);
|
||||
|
||||
this.colorSchemeMediaQuery.addEventListener('change', this.onColorSchemeChanged);
|
||||
@@ -337,9 +337,9 @@ export class App implements AfterViewInit, OnInit, OnDestroy {
|
||||
|
||||
// workaround to allow fetching of Map values in the order they were inserted
|
||||
// https://github.com/angular/angular/issues/31420
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
asIsOrder() {
|
||||
return 1;
|
||||
}
|
||||
@@ -376,34 +376,26 @@ export class App implements AfterViewInit, OnInit, OnDestroy {
|
||||
return this.downloads.configuration['ALLOW_YTDL_OPTIONS_OVERRIDES'] === true;
|
||||
}
|
||||
|
||||
allowCustomDir(tag: string) {
|
||||
if (this.downloads.configuration['CREATE_CUSTOM_DIRS']) {
|
||||
return tag;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
searchFolder: OperatorFunction<string, readonly string[]> = (text$: Observable<string>) => {
|
||||
const debouncedText$ = text$.pipe(debounceTime(150), distinctUntilChanged());
|
||||
const clicksWithClosedPopup$ = this.folderClick$.pipe(
|
||||
filter(() => !this.folderTypeahead()?.isPopupOpen()),
|
||||
);
|
||||
return merge(debouncedText$, this.folderFocus$, clicksWithClosedPopup$).pipe(
|
||||
map(term => {
|
||||
const dirs = this.isAudioType()
|
||||
? (this.downloads.customDirs?.['audio_download_dir'] ?? [])
|
||||
: (this.downloads.customDirs?.['download_dir'] ?? []);
|
||||
const t = (term ?? '').toLowerCase();
|
||||
return (t === '' ? dirs : dirs.filter(d => d.toLowerCase().includes(t))).slice(0, 10);
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
isAudioType() {
|
||||
return this.downloadType === 'audio';
|
||||
}
|
||||
|
||||
getMatchingCustomDir() : Observable<string[]> {
|
||||
return this.downloads.customDirsChanged.asObservable().pipe(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
map((output: any) => {
|
||||
// Keep logic consistent with app/ytdl.py
|
||||
if (this.isAudioType()) {
|
||||
console.debug("Showing audio-specific download directories");
|
||||
return output["audio_download_dir"];
|
||||
} else {
|
||||
console.debug("Showing default download directories");
|
||||
return output["download_dir"];
|
||||
}
|
||||
}),
|
||||
distinctUntilChanged((prev, curr) => JSON.stringify(prev) === JSON.stringify(curr))
|
||||
);
|
||||
}
|
||||
|
||||
getYtdlOptionsUpdateTime() {
|
||||
this.downloads.ytdlOptionsChanged.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
@@ -1471,7 +1463,7 @@ export class App implements AfterViewInit, OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
fetchVersionInfo(): void {
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
const baseUrl = `${window.location.origin}${window.location.pathname.replace(/\/[^\/]*$/, '/')}`;
|
||||
const versionUrl = `${baseUrl}version`;
|
||||
this.http.get<{ 'yt-dlp': string, version: string }>(versionUrl)
|
||||
|
||||
Reference in New Issue
Block a user