feat: Implement chapter splitting functionality with UI controls, yt-dlp integration, and chapter file tracking.
This commit is contained in:
@@ -27,79 +27,79 @@ export class DownloadsService {
|
||||
|
||||
constructor() {
|
||||
this.socket.fromEvent('all')
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
this.loading = false;
|
||||
const data: [[[string, Download]], [[string, Download]]] = JSON.parse(strdata);
|
||||
this.queue.clear();
|
||||
data[0].forEach(entry => this.queue.set(...entry));
|
||||
this.done.clear();
|
||||
data[1].forEach(entry => this.done.set(...entry));
|
||||
this.queueChanged.next(null);
|
||||
this.doneChanged.next(null);
|
||||
});
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
this.loading = false;
|
||||
const data: [[[string, Download]], [[string, Download]]] = JSON.parse(strdata);
|
||||
this.queue.clear();
|
||||
data[0].forEach(entry => this.queue.set(...entry));
|
||||
this.done.clear();
|
||||
data[1].forEach(entry => this.done.set(...entry));
|
||||
this.queueChanged.next(null);
|
||||
this.doneChanged.next(null);
|
||||
});
|
||||
this.socket.fromEvent('added')
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
const data: Download = JSON.parse(strdata);
|
||||
this.queue.set(data.url, data);
|
||||
this.queueChanged.next(null);
|
||||
});
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
const data: Download = JSON.parse(strdata);
|
||||
this.queue.set(data.url, data);
|
||||
this.queueChanged.next(null);
|
||||
});
|
||||
this.socket.fromEvent('updated')
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
const data: Download = JSON.parse(strdata);
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
const data: Download = JSON.parse(strdata);
|
||||
const dl: Download | undefined = this.queue.get(data.url);
|
||||
data.checked = !!dl?.checked;
|
||||
data.deleting = !!dl?.deleting;
|
||||
this.queue.set(data.url, data);
|
||||
this.updated.next(null);
|
||||
});
|
||||
data.checked = !!dl?.checked;
|
||||
data.deleting = !!dl?.deleting;
|
||||
this.queue.set(data.url, data);
|
||||
this.updated.next(null);
|
||||
});
|
||||
this.socket.fromEvent('completed')
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
const data: Download = JSON.parse(strdata);
|
||||
this.queue.delete(data.url);
|
||||
this.done.set(data.url, data);
|
||||
this.queueChanged.next(null);
|
||||
this.doneChanged.next(null);
|
||||
});
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
const data: Download = JSON.parse(strdata);
|
||||
this.queue.delete(data.url);
|
||||
this.done.set(data.url, data);
|
||||
this.queueChanged.next(null);
|
||||
this.doneChanged.next(null);
|
||||
});
|
||||
this.socket.fromEvent('canceled')
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
const data: string = JSON.parse(strdata);
|
||||
this.queue.delete(data);
|
||||
this.queueChanged.next(null);
|
||||
});
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
const data: string = JSON.parse(strdata);
|
||||
this.queue.delete(data);
|
||||
this.queueChanged.next(null);
|
||||
});
|
||||
this.socket.fromEvent('cleared')
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
const data: string = JSON.parse(strdata);
|
||||
this.done.delete(data);
|
||||
this.doneChanged.next(null);
|
||||
});
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
const data: string = JSON.parse(strdata);
|
||||
this.done.delete(data);
|
||||
this.doneChanged.next(null);
|
||||
});
|
||||
this.socket.fromEvent('configuration')
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
const data = JSON.parse(strdata);
|
||||
console.debug("got configuration:", data);
|
||||
this.configuration = data;
|
||||
this.configurationChanged.next(data);
|
||||
});
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
const data = JSON.parse(strdata);
|
||||
console.debug("got configuration:", data);
|
||||
this.configuration = data;
|
||||
this.configurationChanged.next(data);
|
||||
});
|
||||
this.socket.fromEvent('custom_dirs')
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
const data = JSON.parse(strdata);
|
||||
console.debug("got custom_dirs:", data);
|
||||
this.customDirs = data;
|
||||
this.customDirsChanged.next(data);
|
||||
});
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
const data = JSON.parse(strdata);
|
||||
console.debug("got custom_dirs:", data);
|
||||
this.customDirs = data;
|
||||
this.customDirsChanged.next(data);
|
||||
});
|
||||
this.socket.fromEvent('ytdl_options_changed')
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
const data = JSON.parse(strdata);
|
||||
this.ytdlOptionsChanged.next(data);
|
||||
});
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe((strdata: string) => {
|
||||
const data = JSON.parse(strdata);
|
||||
this.ytdlOptionsChanged.next(data);
|
||||
});
|
||||
}
|
||||
|
||||
handleHTTPError(error: HttpErrorResponse) {
|
||||
@@ -107,8 +107,8 @@ export class DownloadsService {
|
||||
return of({status: 'error', msg: msg})
|
||||
}
|
||||
|
||||
public add(url: string, quality: string, format: string, folder: string, customNamePrefix: string, playlistStrictMode: boolean, playlistItemLimit: number, autoStart: boolean) {
|
||||
return this.http.post<Status>('add', {url: url, quality: quality, format: format, folder: folder, custom_name_prefix: customNamePrefix, playlist_strict_mode: playlistStrictMode, playlist_item_limit: playlistItemLimit, auto_start: autoStart}).pipe(
|
||||
public add(url: string, quality: string, format: string, folder: string, customNamePrefix: string, playlistStrictMode: boolean, playlistItemLimit: number, autoStart: boolean, splitByChapters: boolean, chapterTemplate: string) {
|
||||
return this.http.post<Status>('add', { url: url, quality: quality, format: format, folder: folder, custom_name_prefix: customNamePrefix, playlist_strict_mode: playlistStrictMode, playlist_item_limit: playlistItemLimit, auto_start: autoStart, split_by_chapters: splitByChapters, chapter_template: chapterTemplate }).pipe(
|
||||
catchError(this.handleHTTPError)
|
||||
);
|
||||
}
|
||||
@@ -123,7 +123,7 @@ export class DownloadsService {
|
||||
if (obj) {
|
||||
obj.deleting = true
|
||||
}
|
||||
});
|
||||
});
|
||||
return this.http.post('delete', {where: where, ids: ids});
|
||||
}
|
||||
|
||||
@@ -145,14 +145,16 @@ export class DownloadsService {
|
||||
}> {
|
||||
const defaultQuality = 'best';
|
||||
const defaultFormat = 'mp4';
|
||||
const defaultFolder = '';
|
||||
const defaultFolder = '';
|
||||
const defaultCustomNamePrefix = '';
|
||||
const defaultPlaylistStrictMode = false;
|
||||
const defaultPlaylistItemLimit = 0;
|
||||
const defaultAutoStart = true;
|
||||
|
||||
const defaultSplitByChapters = false;
|
||||
const defaultChapterTemplate = '%(section_number)02d - %(section_title)s.%(ext)s';
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this.add(url, defaultQuality, defaultFormat, defaultFolder, defaultCustomNamePrefix, defaultPlaylistStrictMode, defaultPlaylistItemLimit, defaultAutoStart)
|
||||
this.add(url, defaultQuality, defaultFormat, defaultFolder, defaultCustomNamePrefix, defaultPlaylistStrictMode, defaultPlaylistItemLimit, defaultAutoStart, defaultSplitByChapters, defaultChapterTemplate)
|
||||
.subscribe({
|
||||
next: (response) => resolve(response),
|
||||
error: (error) => reject(error)
|
||||
@@ -162,6 +164,6 @@ export class DownloadsService {
|
||||
public exportQueueUrls(): string[] {
|
||||
return Array.from(this.queue.values()).map(download => download.url);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user