feat: cancel playlist adding mid-operation (closes #840)

This commit is contained in:
ddmoney420
2026-03-01 19:11:29 -07:00
parent fd3aaea9d9
commit 880eda8435
5 changed files with 39 additions and 11 deletions
+6
View File
@@ -302,6 +302,11 @@ async def add(request):
) )
return web.Response(text=serializer.encode(status)) 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') @routes.post(config.URL_PREFIX + 'delete')
async def delete(request): async def delete(request):
post = await request.json() post = await request.json()
@@ -433,6 +438,7 @@ async def add_cors(request):
return web.Response(text=serializer.encode({"status": "ok"})) 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 + 'add', add_cors)
app.router.add_route('OPTIONS', config.URL_PREFIX + 'cancel-add', add_cors)
async def on_prepare(request, response): async def on_prepare(request, response):
if 'Origin' in request.headers: if 'Origin' in request.headers:
+10
View File
@@ -535,6 +535,11 @@ class DownloadQueue:
self.active_downloads = set() self.active_downloads = set()
self.semaphore = asyncio.Semaphore(int(self.config.MAX_CONCURRENT_DOWNLOADS)) self.semaphore = asyncio.Semaphore(int(self.config.MAX_CONCURRENT_DOWNLOADS))
self.done.load() 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): async def __import_queue(self):
for k, v in self.queue.saved_items(): 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') log.info(f'Item limit is set. Processing only first {playlist_item_limit} entries')
entries = entries[:playlist_item_limit] entries = entries[:playlist_item_limit]
for index, etr in enumerate(entries, start=1): 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["_type"] = "video"
etr[etype] = entry.get("id") or entry.get("channel_id") or entry.get("channel") 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) 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'{playlist_item_limit=} {auto_start=} {split_by_chapters=} {chapter_template=} '
f'{subtitle_format=} {subtitle_language=} {subtitle_mode=}' f'{subtitle_format=} {subtitle_language=} {subtitle_mode=}'
) )
if already is None:
self._add_canceled = False
already = set() if already is None else already already = set() if already is None else already
if url in already: if url in already:
log.info('recursion detected, skipping') log.info('recursion detected, skipping')
+11 -9
View File
@@ -98,15 +98,17 @@
name="addUrl" name="addUrl"
[(ngModel)]="addUrl" [(ngModel)]="addUrl"
[disabled]="addInProgress || downloads.loading"> [disabled]="addInProgress || downloads.loading">
<button class="btn btn-primary btn-lg px-4" @if (addInProgress) {
type="submit" <button class="btn btn-danger btn-lg px-3" type="button" (click)="cancelAdding()">
(click)="addDownload()" <fa-icon [icon]="faTimesCircle" class="me-1" /> Cancel
[disabled]="addInProgress || downloads.loading"> </button>
@if (addInProgress) { } @else {
<span class="spinner-border spinner-border-sm" role="status" id="add-spinner"></span> <button class="btn btn-primary btn-lg px-4" type="submit"
} (click)="addDownload()"
{{ addInProgress ? "Adding..." : "Download" }} [disabled]="downloads.loading">
</button> Download
</button>
}
</div> </div>
</div> </div>
</div> </div>
+7
View File
@@ -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) { downloadItemByKey(id: string) {
this.downloads.startById([id]).subscribe(); this.downloads.startById([id]).subscribe();
} }
+5 -2
View File
@@ -208,6 +208,9 @@ export class DownloadsService {
public exportQueueUrls(): string[] { public exportQueueUrls(): string[] {
return Array.from(this.queue.values()).map(download => download.url); return Array.from(this.queue.values()).map(download => download.url);
} }
public cancelAdd() {
return this.http.post<any>('cancel-add', {}).pipe(
catchError(this.handleHTTPError)
);
}
} }