diff --git a/app/main.py b/app/main.py index 3240744..dad519b 100644 --- a/app/main.py +++ b/app/main.py @@ -302,6 +302,11 @@ async def add(request): ) return web.Response(text=serializer.encode(status)) +@routes.post(config.URL_PREFIX + 'cancel-add') +async def cancel_add(request): + dqueue.cancel_add() + return web.Response(text=serializer.encode({'status': 'ok'}), content_type='application/json') + @routes.post(config.URL_PREFIX + 'delete') async def delete(request): post = await request.json() @@ -433,6 +438,7 @@ async def add_cors(request): return web.Response(text=serializer.encode({"status": "ok"})) app.router.add_route('OPTIONS', config.URL_PREFIX + 'add', add_cors) +app.router.add_route('OPTIONS', config.URL_PREFIX + 'cancel-add', add_cors) async def on_prepare(request, response): if 'Origin' in request.headers: diff --git a/app/ytdl.py b/app/ytdl.py index 18e47ab..b8e4b0c 100644 --- a/app/ytdl.py +++ b/app/ytdl.py @@ -535,6 +535,11 @@ class DownloadQueue: self.active_downloads = set() self.semaphore = asyncio.Semaphore(int(self.config.MAX_CONCURRENT_DOWNLOADS)) self.done.load() + self._add_canceled = False + + def cancel_add(self): + self._add_canceled = True + log.info('Playlist add operation canceled by user') async def __import_queue(self): for k, v in self.queue.saved_items(): @@ -699,6 +704,9 @@ class DownloadQueue: log.info(f'Item limit is set. Processing only first {playlist_item_limit} entries') entries = entries[:playlist_item_limit] for index, etr in enumerate(entries, start=1): + if self._add_canceled: + log.info(f'Playlist add canceled after processing {len(already)} entries') + return {'status': 'ok', 'msg': f'Canceled - added {len(already)} items before cancel'} etr["_type"] = "video" etr[etype] = entry.get("id") or entry.get("channel_id") or entry.get("channel") etr[f"{etype}_index"] = '{{0:0{0:d}d}}'.format(index_digits).format(index) @@ -771,6 +779,8 @@ class DownloadQueue: f'{playlist_item_limit=} {auto_start=} {split_by_chapters=} {chapter_template=} ' f'{subtitle_format=} {subtitle_language=} {subtitle_mode=}' ) + if already is None: + self._add_canceled = False already = set() if already is None else already if url in already: log.info('recursion detected, skipping') diff --git a/ui/src/app/app.html b/ui/src/app/app.html index 6244667..00bcdb9 100644 --- a/ui/src/app/app.html +++ b/ui/src/app/app.html @@ -98,15 +98,17 @@ name="addUrl" [(ngModel)]="addUrl" [disabled]="addInProgress || downloads.loading"> - + @if (addInProgress) { + + } @else { + + } diff --git a/ui/src/app/app.ts b/ui/src/app/app.ts index 17281c6..fa33ce3 100644 --- a/ui/src/app/app.ts +++ b/ui/src/app/app.ts @@ -433,6 +433,13 @@ export class App implements AfterViewInit, OnInit { }); } + cancelAdding() { + this.downloads.cancelAdd().subscribe({ + next: () => { this.addInProgress = false; }, + error: () => { this.addInProgress = false; } + }); + } + downloadItemByKey(id: string) { this.downloads.startById([id]).subscribe(); } diff --git a/ui/src/app/services/downloads.service.ts b/ui/src/app/services/downloads.service.ts index 52690c8..4d10edf 100644 --- a/ui/src/app/services/downloads.service.ts +++ b/ui/src/app/services/downloads.service.ts @@ -208,6 +208,9 @@ export class DownloadsService { public exportQueueUrls(): string[] { return Array.from(this.queue.values()).map(download => download.url); } - - + public cancelAdd() { + return this.http.post('cancel-add', {}).pipe( + catchError(this.handleHTTPError) + ); + } }