mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-07-10 15:32:48 -07:00
WebUI: Add 'Confirm torrent recheck' option
This PR adds setting & confirmation dialog for torrent recheck. Closes #19557. PR #21348.
This commit is contained in:
parent
183c7c75b1
commit
c3224459db
7 changed files with 136 additions and 24 deletions
|
@ -368,6 +368,8 @@ void AppController::preferencesAction()
|
||||||
data[u"save_statistics_interval"_s] = static_cast<int>(session->saveStatisticsInterval().count());
|
data[u"save_statistics_interval"_s] = static_cast<int>(session->saveStatisticsInterval().count());
|
||||||
// .torrent file size limit
|
// .torrent file size limit
|
||||||
data[u"torrent_file_size_limit"_s] = pref->getTorrentFileSizeLimit();
|
data[u"torrent_file_size_limit"_s] = pref->getTorrentFileSizeLimit();
|
||||||
|
// Confirm torrent recheck
|
||||||
|
data[u"confirm_torrent_recheck"_s] = pref->confirmTorrentRecheck();
|
||||||
// Recheck completed torrents
|
// Recheck completed torrents
|
||||||
data[u"recheck_completed_torrents"_s] = pref->recheckTorrentsOnCompletion();
|
data[u"recheck_completed_torrents"_s] = pref->recheckTorrentsOnCompletion();
|
||||||
// Customize application instance name
|
// Customize application instance name
|
||||||
|
@ -977,6 +979,9 @@ void AppController::setPreferencesAction()
|
||||||
// .torrent file size limit
|
// .torrent file size limit
|
||||||
if (hasKey(u"torrent_file_size_limit"_s))
|
if (hasKey(u"torrent_file_size_limit"_s))
|
||||||
pref->setTorrentFileSizeLimit(it.value().toLongLong());
|
pref->setTorrentFileSizeLimit(it.value().toLongLong());
|
||||||
|
// Confirm torrent recheck
|
||||||
|
if (hasKey(u"confirm_torrent_recheck"_s))
|
||||||
|
pref->setConfirmTorrentRecheck(it.value().toBool());
|
||||||
// Recheck completed torrents
|
// Recheck completed torrents
|
||||||
if (hasKey(u"recheck_completed_torrents"_s))
|
if (hasKey(u"recheck_completed_torrents"_s))
|
||||||
pref->recheckTorrentsOnCompletion(it.value().toBool());
|
pref->recheckTorrentsOnCompletion(it.value().toBool());
|
||||||
|
|
|
@ -755,23 +755,23 @@ td.statusBarSeparator {
|
||||||
color: var(--color-text-white);
|
color: var(--color-text-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Confirm deletion dialog */
|
/* Modals */
|
||||||
|
|
||||||
#confirmDeletionPage * {
|
.modalDialog * {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
#confirmDeletionPage_content {
|
.modalDialog .mochaContent.pad {
|
||||||
display: flex !important; /* override for default mocha inline style */
|
display: flex !important; /* override for default mocha inline style */
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#confirmDeletionPage_content > :last-child {
|
.modalDialog .mochaContent.pad > :last-child {
|
||||||
align-self: flex-end;
|
align-self: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
#confirmDeletionDialog {
|
.modalDialog .mochaContent.pad > :first-child {
|
||||||
margin: auto 0;
|
margin: auto 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -792,10 +792,11 @@ td.statusBarSeparator {
|
||||||
vertical-align: -1px;
|
vertical-align: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#deleteTorrentMessage {
|
.dialogMessage {
|
||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.genericConfirmGrid,
|
||||||
.confirmDeletionGrid {
|
.confirmDeletionGrid {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: grid;
|
display: grid;
|
||||||
|
@ -804,6 +805,7 @@ td.statusBarSeparator {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.confirmGridItem,
|
||||||
.deletionGridItem {
|
.deletionGridItem {
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
}
|
}
|
||||||
|
@ -812,8 +814,13 @@ td.statusBarSeparator {
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.confirmWarning,
|
||||||
.confirmDialogWarning {
|
.confirmDialogWarning {
|
||||||
background: url("../images/dialog-warning.svg") center center no-repeat;
|
background: url("../images/dialog-warning.svg") center center no-repeat;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
width: 38px;
|
width: 38px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.confirmWarning {
|
||||||
|
background-image: url("../images/help-about.svg");
|
||||||
|
}
|
||||||
|
|
|
@ -48,16 +48,26 @@ window.qBittorrent.Dialog ??= (() => {
|
||||||
|
|
||||||
const deepFreeze = (obj) => {
|
const deepFreeze = (obj) => {
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#examples
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#examples
|
||||||
|
// accounts for circular refs
|
||||||
|
const frozen = new WeakSet();
|
||||||
|
const deepFreezeSafe = (obj) => {
|
||||||
|
if (frozen.has(obj))
|
||||||
|
return;
|
||||||
|
|
||||||
|
frozen.add(obj);
|
||||||
|
|
||||||
const keys = Reflect.ownKeys(obj);
|
const keys = Reflect.ownKeys(obj);
|
||||||
for (const key of keys) {
|
for (const key of keys) {
|
||||||
const value = obj[key];
|
const value = obj[key];
|
||||||
if ((value && (typeof value === "object")) || (typeof value === "function"))
|
if ((value && (typeof value === "object")) || (typeof value === "function"))
|
||||||
deepFreeze(value);
|
deepFreezeSafe(value);
|
||||||
}
|
}
|
||||||
Object.freeze(obj);
|
Object.freeze(obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
deepFreezeSafe(obj);
|
||||||
|
};
|
||||||
|
|
||||||
const baseModalOptions = Object.assign(Object.create(null), {
|
const baseModalOptions = Object.assign(Object.create(null), {
|
||||||
addClass: "modalDialog",
|
addClass: "modalDialog",
|
||||||
collapsible: false,
|
collapsible: false,
|
||||||
|
@ -76,7 +86,11 @@ window.qBittorrent.Dialog ??= (() => {
|
||||||
left: 5
|
left: 5
|
||||||
},
|
},
|
||||||
resizable: true,
|
resizable: true,
|
||||||
width: 480
|
width: 480,
|
||||||
|
onCloseComplete: function() {
|
||||||
|
// make sure overlay is properly hidden upon modal closing
|
||||||
|
document.getElementById("modalOverlay").style.display = "none";
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
deepFreeze(baseModalOptions);
|
deepFreeze(baseModalOptions);
|
||||||
|
@ -541,15 +555,31 @@ const initializeWindows = function() {
|
||||||
|
|
||||||
recheckFN = function() {
|
recheckFN = function() {
|
||||||
const hashes = torrentsTable.selectedRowsIds();
|
const hashes = torrentsTable.selectedRowsIds();
|
||||||
if (hashes.length) {
|
if (hashes.length > 0) {
|
||||||
|
if (window.qBittorrent.Cache.preferences.get().confirm_torrent_recheck) {
|
||||||
|
new MochaUI.Modal({
|
||||||
|
...window.qBittorrent.Dialog.baseModalOptions,
|
||||||
|
id: "confirmRecheckDialog",
|
||||||
|
title: "QBT_TR(Recheck confirmation)QBT_TR[CONTEXT=confirmRecheckDialog]",
|
||||||
|
data: { hashes: hashes },
|
||||||
|
contentURL: "views/confirmRecheck.html"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
new Request({
|
new Request({
|
||||||
url: "api/v2/torrents/recheck",
|
url: "api/v2/torrents/recheck",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: {
|
data: {
|
||||||
hashes: hashes.join("|"),
|
"hashes": hashes.join("|"),
|
||||||
|
},
|
||||||
|
onSuccess: function() {
|
||||||
|
updateMainData();
|
||||||
|
},
|
||||||
|
onFailure: function() {
|
||||||
|
alert("QBT_TR(Unable to recheck torrents.)QBT_TR[CONTEXT=HttpServer]");
|
||||||
}
|
}
|
||||||
}).send();
|
}).send();
|
||||||
updateMainData();
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
59
src/webui/www/private/views/confirmRecheck.html
Normal file
59
src/webui/www/private/views/confirmRecheck.html
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<div id="confirmRecheckDialog">
|
||||||
|
<div class="genericConfirmGrid">
|
||||||
|
<span class="confirmGridItem confirmWarning"></span>
|
||||||
|
<span class="confirmGridItem dialogMessage" id="confirmRecheckMessage"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="button" value="QBT_TR(Yes)QBT_TR[CONTEXT=MainWindow]" id="confirmRecheckButton">
|
||||||
|
<input type="button" value="QBT_TR(No)QBT_TR[CONTEXT=MainWindow]" id="cancelRecheckButton">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
(() => {
|
||||||
|
const confirmButton = document.getElementById("confirmRecheckButton");
|
||||||
|
const cancelButton = document.getElementById("cancelRecheckButton");
|
||||||
|
const confirmText = document.getElementById("confirmRecheckMessage");
|
||||||
|
|
||||||
|
const {
|
||||||
|
options: { data: { hashes } },
|
||||||
|
windowEl
|
||||||
|
} = window.MUI.Windows.instances["confirmRecheckDialog"];
|
||||||
|
|
||||||
|
confirmText.textContent = "QBT_TR(Are you sure you want to recheck the selected torrent(s)?)QBT_TR[CONTEXT=confirmRecheckDialog]";
|
||||||
|
|
||||||
|
cancelButton.addEventListener("click", (e) => { window.qBittorrent.Client.closeWindow("confirmRecheckDialog"); });
|
||||||
|
confirmButton.addEventListener("click", (e) => {
|
||||||
|
new Request({
|
||||||
|
url: "api/v2/torrents/recheck",
|
||||||
|
method: "post",
|
||||||
|
data: {
|
||||||
|
hashes: hashes.join("|"),
|
||||||
|
},
|
||||||
|
onSuccess: function() {
|
||||||
|
updateMainData();
|
||||||
|
window.qBittorrent.Client.closeWindow("confirmRecheckDialog");
|
||||||
|
},
|
||||||
|
onFailure: function() {
|
||||||
|
alert("QBT_TR(Unable to recheck torrents.)QBT_TR[CONTEXT=HttpServer]");
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
});
|
||||||
|
|
||||||
|
// set tabindex so window element receives keydown events
|
||||||
|
windowEl.setAttribute("tabindex", "-1");
|
||||||
|
windowEl.focus();
|
||||||
|
windowEl.addEventListener("keydown", (e) => {
|
||||||
|
switch (e.key) {
|
||||||
|
case "Enter":
|
||||||
|
confirmButton.click();
|
||||||
|
break;
|
||||||
|
case "Escape":
|
||||||
|
window.qBittorrent.Client.closeWindow("confirmRecheckDialog");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
|
@ -1,7 +1,7 @@
|
||||||
<div id="confirmDeletionDialog">
|
<div id="confirmDeletionDialog">
|
||||||
<div class="confirmDeletionGrid">
|
<div class="confirmDeletionGrid">
|
||||||
<span class="deletionGridItem confirmDialogWarning"></span>
|
<span class="deletionGridItem confirmDialogWarning"></span>
|
||||||
<span class="deletionGridItem" id="deleteTorrentMessage"></span>
|
<span class="deletionGridItem dialogMessage" id="deleteTorrentMessage"></span>
|
||||||
<span class="deletionGridItem">
|
<span class="deletionGridItem">
|
||||||
<button class="disabled" type="button" id="rememberBtn" title="QBT_TR(Remember choice)QBT_TR[CONTEXT=HttpServer]" aria-label="QBT_TR(Remember choice)QBT_TR[CONTEXT=HttpServer]" disabled></button>
|
<button class="disabled" type="button" id="rememberBtn" title="QBT_TR(Remember choice)QBT_TR[CONTEXT=HttpServer]" aria-label="QBT_TR(Remember choice)QBT_TR[CONTEXT=HttpServer]" disabled></button>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -1168,6 +1168,14 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
||||||
<input type="text" id="torrentFileSizeLimit" style="width: 15em;"> QBT_TR(MiB)QBT_TR[CONTEXT=OptionsDialog]
|
<input type="text" id="torrentFileSizeLimit" style="width: 15em;"> QBT_TR(MiB)QBT_TR[CONTEXT=OptionsDialog]
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="confirmTorrentRecheck">QBT_TR(Confirm torrent recheck:)QBT_TR[CONTEXT=OptionsDialog]</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" id="confirmTorrentRecheck">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<label for="recheckTorrentsOnCompletion">QBT_TR(Recheck torrents on completion:)QBT_TR[CONTEXT=OptionsDialog]</label>
|
<label for="recheckTorrentsOnCompletion">QBT_TR(Recheck torrents on completion:)QBT_TR[CONTEXT=OptionsDialog]</label>
|
||||||
|
@ -2464,6 +2472,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
||||||
$("saveResumeDataInterval").value = pref.save_resume_data_interval;
|
$("saveResumeDataInterval").value = pref.save_resume_data_interval;
|
||||||
$("saveStatisticsInterval").value = pref.save_statistics_interval;
|
$("saveStatisticsInterval").value = pref.save_statistics_interval;
|
||||||
$("torrentFileSizeLimit").value = (pref.torrent_file_size_limit / 1024 / 1024);
|
$("torrentFileSizeLimit").value = (pref.torrent_file_size_limit / 1024 / 1024);
|
||||||
|
document.getElementById("confirmTorrentRecheck").checked = pref.confirm_torrent_recheck;
|
||||||
$("recheckTorrentsOnCompletion").checked = pref.recheck_completed_torrents;
|
$("recheckTorrentsOnCompletion").checked = pref.recheck_completed_torrents;
|
||||||
$("appInstanceName").value = pref.app_instance_name;
|
$("appInstanceName").value = pref.app_instance_name;
|
||||||
$("refreshInterval").value = pref.refresh_interval;
|
$("refreshInterval").value = pref.refresh_interval;
|
||||||
|
@ -2920,6 +2929,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
||||||
settings["save_resume_data_interval"] = Number($("saveResumeDataInterval").value);
|
settings["save_resume_data_interval"] = Number($("saveResumeDataInterval").value);
|
||||||
settings["save_statistics_interval"] = Number($("saveStatisticsInterval").value);
|
settings["save_statistics_interval"] = Number($("saveStatisticsInterval").value);
|
||||||
settings["torrent_file_size_limit"] = ($("torrentFileSizeLimit").value * 1024 * 1024);
|
settings["torrent_file_size_limit"] = ($("torrentFileSizeLimit").value * 1024 * 1024);
|
||||||
|
settings["confirm_torrent_recheck"] = document.getElementById("confirmTorrentRecheck").checked;
|
||||||
settings["recheck_completed_torrents"] = $("recheckTorrentsOnCompletion").checked;
|
settings["recheck_completed_torrents"] = $("recheckTorrentsOnCompletion").checked;
|
||||||
settings["app_instance_name"] = $("appInstanceName").value;
|
settings["app_instance_name"] = $("appInstanceName").value;
|
||||||
settings["refresh_interval"] = Number($("refreshInterval").value);
|
settings["refresh_interval"] = Number($("refreshInterval").value);
|
||||||
|
|
|
@ -421,6 +421,7 @@
|
||||||
<file>private/views/about.html</file>
|
<file>private/views/about.html</file>
|
||||||
<file>private/views/aboutToolbar.html</file>
|
<file>private/views/aboutToolbar.html</file>
|
||||||
<file>private/views/confirmdeletion.html</file>
|
<file>private/views/confirmdeletion.html</file>
|
||||||
|
<file>private/views/confirmRecheck.html</file>
|
||||||
<file>private/views/filters.html</file>
|
<file>private/views/filters.html</file>
|
||||||
<file>private/views/installsearchplugin.html</file>
|
<file>private/views/installsearchplugin.html</file>
|
||||||
<file>private/views/log.html</file>
|
<file>private/views/log.html</file>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue