Add cancel button

playlist_cancel
aandrew-me 2 weeks ago
parent 6dc60bfaab
commit cfe3a1de53

@ -28,6 +28,17 @@
bottom: 8px;
}
#stopDownload {
display: none;
position: relative;
bottom: 8px;
background-color: var(--redBtn);
}
#stopDownload:active {
background-color: var(--redBtn-bottom);
}
#audioBox {
display: none;
}
@ -187,6 +198,7 @@
<h2 id="playlistName"></h2>
<button class="submitBtn" id="openDownloads" data-translate="openDownloadFolder">Open download folder</button>
<button class="submitBtn" id="stopDownload" data-translate="cancel">Cancel</button>
<div id="list">
</div>

@ -18,6 +18,9 @@ const playlistDownloader = {
playlistName: "",
originalCount: 0,
currentDownloadProcess: null,
currentAbortController: null,
isDownloading: false,
isCancelled: false,
},
config: {
@ -53,6 +56,7 @@ const playlistDownloader = {
selectLocationBtn: document.getElementById("selectLocation"),
pathDisplay: document.getElementById("path"),
openDownloadsBtn: document.getElementById("openDownloads"),
stopDownloadBtn: document.getElementById("stopDownload"),
videoToggle: document.getElementById("videoToggle"),
audioToggle: document.getElementById("audioToggle"),
@ -150,7 +154,9 @@ const playlistDownloader = {
document.activeElement.tagName !== "INPUT" &&
document.activeElement.tagName !== "TEXTAREA")
) {
this.pasteLink();
if (!this.state.isDownloading) {
this.pasteLink();
}
}
});
@ -185,6 +191,9 @@ const playlistDownloader = {
this.ui.openDownloadsBtn.addEventListener("click", () =>
this.openDownloadsFolder(),
);
this.ui.stopDownloadBtn.addEventListener("click", () =>
this.stopDownload(),
);
this.ui.closeHiddenBtn.addEventListener("click", () =>
this.hideOptions(true),
);
@ -214,6 +223,8 @@ const playlistDownloader = {
},
async startDownload(type) {
if (this.state.isDownloading) return;
try {
this.state.url = this.validateUrl(this.state.url);
} catch (_) {
@ -222,49 +233,66 @@ const playlistDownloader = {
return;
}
await this.updateDynamicConfig();
this.hideOptions();
const controller = new AbortController();
const baseArgs = this.buildBaseArgs();
let specificArgs = [];
try {
await this.updateDynamicConfig();
this.hideOptions();
this.state.isDownloading = true;
this.state.isCancelled = false;
this.state.currentAbortController = new AbortController();
const baseArgs = this.buildBaseArgs();
let specificArgs = [];
switch (type) {
case "video":
specificArgs = this.getVideoArgs();
break;
case "audio":
specificArgs = this.getAudioArgs();
break;
case "thumbnails":
specificArgs = this.getThumbnailArgs();
break;
case "links":
specificArgs = this.getLinkArgs();
break;
}
switch (type) {
case "video":
specificArgs = this.getVideoArgs();
break;
case "audio":
specificArgs = this.getAudioArgs();
break;
case "thumbnails":
specificArgs = this.getThumbnailArgs();
break;
case "links":
specificArgs = this.getLinkArgs();
break;
}
const allArgs = [...baseArgs, ...specificArgs, this.state.url].filter(
Boolean,
);
const allArgs = [...baseArgs, ...specificArgs, this.state.url].filter(
Boolean,
);
console.log(`Command: ${this.state.ytDlpPath}`, allArgs.join(" "));
this.state.currentDownloadProcess = this.state.ytDlpWrap.exec(
allArgs,
{shell: false},
this.state.currentAbortController.signal,
);
console.log(`Command: ${this.state.ytDlpPath}`, allArgs.join(" "));
this.state.currentDownloadProcess = this.state.ytDlpWrap.exec(
allArgs,
{shell: false},
controller.signal,
);
document.addEventListener("beforeunload", () => {
if (
this.state.currentDownloadProcess &&
!this.state.currentDownloadProcess.killed
) {
this.state.currentDownloadProcess.kill();
}
});
// TODO: Avoid duplication of event listeners
document.addEventListener("beforeunload", () => {
if (this.state.currentAbortController) {
try {
this.state.currentAbortController.abort();
} catch (e) {}
}
if (
this.state.currentDownloadProcess &&
this.state.currentDownloadProcess.ytDlpProcess &&
!this.state.currentDownloadProcess.ytDlpProcess.killed
) {
try {
this.state.currentDownloadProcess.ytDlpProcess.kill();
} catch (e) {}
}
});
this.handleDownloadEvents(this.state.currentDownloadProcess, type);
this.handleDownloadEvents(this.state.currentDownloadProcess, type);
} catch (error) {
this.showError(error);
}
},
buildBaseArgs() {
@ -481,7 +509,29 @@ const playlistDownloader = {
process.on("close", () => this.finishDownload(count));
},
stopDownload() {
this.state.isCancelled = true;
if (this.state.currentAbortController) {
try {
this.state.currentAbortController.abort();
} catch (e) {
console.error("Failed to abort controller:", e);
}
}
if (
this.state.currentDownloadProcess &&
this.state.currentDownloadProcess.ytDlpProcess
) {
try {
this.state.currentDownloadProcess.ytDlpProcess.kill();
} catch (e) {
console.error("Failed to kill ytDlpProcess:", e);
}
}
},
pasteLink() {
if (this.state.isDownloading) return;
this.state.url = clipboard.readText();
this.ui.linkDisplay.textContent = ` ${this.state.url}`;
this.ui.optionsContainer.style.display = "block";
@ -571,6 +621,7 @@ const playlistDownloader = {
this.ui.errorDetails.style.display = "none";
this.ui.errorDetails.textContent = "";
this.ui.errorMsgDisplay.style.display = "none";
this.ui.stopDownloadBtn.style.display = "none";
if (!justHide) {
this.ui.playlistNameDisplay.textContent = `${window.i18n.__(
@ -578,10 +629,26 @@ const playlistDownloader = {
)}...`;
this.ui.pasteLinkBtn.style.display = "none";
this.ui.openDownloadsBtn.style.display = "inline-block";
this.ui.stopDownloadBtn.style.display = "inline-block";
}
},
finishDownload(count) {
if (!this.state.isDownloading) return;
this.state.isDownloading = false;
this.ui.stopDownloadBtn.style.display = "none";
if (this.state.isCancelled) {
this.state.isCancelled = false;
const lastProgress = document.getElementById(`p${count}`);
if (lastProgress) {
lastProgress.textContent = window.i18n.__("cancel");
}
this.ui.playlistNameDisplay.textContent = window.i18n.__("cancel");
this.ui.pasteLinkBtn.style.display = "inline-block";
return;
}
const lastProgress = document.getElementById(`p${count}`);
if (lastProgress)
lastProgress.textContent = window.i18n.__("fileSaved");
@ -597,6 +664,17 @@ const playlistDownloader = {
},
showError(error) {
const wasDownloading = this.state.isDownloading;
this.state.isDownloading = false;
this.ui.stopDownloadBtn.style.display = "none";
if (this.state.isCancelled && wasDownloading) {
this.state.isCancelled = false;
this.ui.playlistNameDisplay.textContent = window.i18n.__("cancel");
this.ui.pasteLinkBtn.style.display = "inline-block";
return;
}
console.error("Download Error:", error.toString());
this.ui.pasteLinkBtn.style.display = "inline-block";
this.ui.openDownloadsBtn.style.display = "none";
@ -663,6 +741,14 @@ const playlistDownloader = {
},
navigate(type, page) {
if (this.state.isDownloading) {
const confirmMsg = window.i18n ? window.i18n.__("cancel_download") + "?" : "Are you sure you want to cancel the download?";
const choice = confirm(confirmMsg);
if (!choice) {
return;
}
this.stopDownload();
}
this.closeMenu();
const event = type === "page" ? "load-page" : "load-win";
ipcRenderer.send(event, path.join(__dirname, page));

@ -181,9 +181,9 @@
"qualityTargetSizeDesc": "Specify target MB",
"targetSizeMB": "Target Size (MB)",
"worst": "Worst",
"best": "Best",
"advancedSettings": "Advanced Settings",
"qualityTargetPercent": "Target %",
"qualityTargetPercentDesc": "Set target % of size",
"targetPercentLabel": "Target Percentage (%)"
"targetPercentLabel": "Target Percentage (%)",
"cancel_download": "Are you sure you want to cancel the download?"
}

Loading…
Cancel
Save