WebUI: Replace slider with native input range

Got rid of Mootools and MochaUI.

PR #22769.
This commit is contained in:
tehcneko 2025-05-27 14:22:13 +08:00 committed by GitHub
commit 84ed24e257
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 173 additions and 483 deletions

View file

@ -418,50 +418,10 @@ a.propButton img {
/* Sliders */
.slider {
clear: both;
font-size: 12px;
font-weight: bold;
margin-bottom: 15px;
margin: 4px;
position: relative;
width: 400px;
}
.sliderWrapper {
font-size: 1px;
height: 9px;
line-height: 1px;
position: relative;
width: 422px;
}
.sliderarea {
background: #f2f2f2 url("../images/slider-area.gif") repeat-x;
border: 1px solid #a3a3a3;
border-bottom: 1px solid #cccccc;
border-left: 1px solid #cccccc;
font-size: 1px;
height: 7px;
left: 0;
line-height: 1px;
overflow: hidden;
padding: 0;
position: absolute;
top: 0;
width: 420px;
}
.sliderknob {
background: url("../images/knob.gif") no-repeat;
cursor: pointer;
font-size: 1px;
height: 9px;
left: 0;
line-height: 1px;
overflow: hidden;
position: absolute;
top: 0;
width: 19px;
z-index: 2;
}
.update {

View file

@ -1,90 +0,0 @@
<!DOCTYPE html>
<html lang="${LANG}" class="dark">
<head>
<meta charset="UTF-8">
<title>QBT_TR(Torrent Download Speed Limiting)QBT_TR[CONTEXT=TransferListWidget]</title>
<link rel="stylesheet" href="css/style.css?v=${CACHEID}" type="text/css">
<script src="scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
<script src="scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
<script src="scripts/lib/mocha.min.js"></script>
<script src="scripts/localpreferences.js?v=${CACHEID}"></script>
<script src="scripts/color-scheme.js?v=${CACHEID}"></script>
<script src="scripts/speedslider.js?v=${CACHEID}"></script>
</head>
<body>
<div style="padding-top: 10px; width: 100%; text-align: center; margin: 0 auto; overflow: hidden">
<div id="dllimitSlider" class="slider">
<div id="dllimitUpdate" class="update">
<label for="dllimitUpdatevalue">QBT_TR(Download limit:)QBT_TR[CONTEXT=PropertiesWidget]</label>
<input type="text" id="dllimitUpdatevalue" size="6" placeholder="∞" style="text-align: center;">
<span id="dlLimitUnit">QBT_TR(KiB/s)QBT_TR[CONTEXT=SpeedLimitDialog]</span>
</div>
<div class="sliderWrapper">
<div id="dllimitSliderknob" class="sliderknob"></div>
<div id="dllimitSliderarea" class="sliderarea"></div>
</div>
<div class="clear"></div>
</div>
<input type="button" id="applyButton" value="QBT_TR(Apply)QBT_TR[CONTEXT=HttpServer]" onclick="setDlLimit()">
</div>
<script>
"use strict";
window.addEventListener("keydown", (event) => {
switch (event.key) {
case "Enter":
event.preventDefault();
document.getElementById("applyButton").click();
break;
case "Escape":
event.preventDefault();
window.parent.qBittorrent.Client.closeFrameWindow(window);
break;
}
});
const hashes = new URLSearchParams(window.location.search).get("hashes").split("|");
const setDlLimit = () => {
const limit = Number(document.getElementById("dllimitUpdatevalue").value) * 1024;
if (hashes[0] === "global") {
fetch("api/v2/transfer/setDownloadLimit", {
method: "POST",
body: new URLSearchParams({
limit: limit
})
})
.then((response) => {
if (!response.ok)
return;
window.parent.updateMainData();
window.parent.qBittorrent.Client.closeFrameWindow(window);
});
}
else {
fetch("api/v2/torrents/setDownloadLimit", {
method: "POST",
body: new URLSearchParams({
hashes: hashes.join("|"),
limit: limit
})
})
.then((response) => {
if (!response.ok)
return;
window.parent.qBittorrent.Client.closeFrameWindow(window);
});
}
};
document.getElementById("dllimitUpdatevalue").focus();
MochaUI.addDlLimitSlider(hashes);
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 B

View file

@ -309,9 +309,10 @@ const initializeWindows = () => {
});
globalUploadLimitFN = () => {
const contentURL = new URL("uploadlimit.html", window.location);
const contentURL = new URL("speedlimit.html", window.location);
contentURL.search = new URLSearchParams({
hashes: "global"
hashes: "global",
type: "upload",
});
new MochaUI.Window({
id: "uploadLimitPage",
@ -334,9 +335,10 @@ const initializeWindows = () => {
if (hashes.length <= 0)
return;
const contentURL = new URL("uploadlimit.html", window.location);
const contentURL = new URL("speedlimit.html", window.location);
contentURL.search = new URLSearchParams({
hashes: hashes.join("|")
hashes: hashes.join("|"),
type: "upload",
});
new MochaUI.Window({
id: "uploadLimitPage",
@ -455,9 +457,10 @@ const initializeWindows = () => {
};
globalDownloadLimitFN = () => {
const contentURL = new URL("downloadlimit.html", window.location);
const contentURL = new URL("speedlimit.html", window.location);
contentURL.search = new URLSearchParams({
hashes: "global"
hashes: "global",
type: "download",
});
new MochaUI.Window({
id: "downloadLimitPage",
@ -498,9 +501,10 @@ const initializeWindows = () => {
if (hashes.length <= 0)
return;
const contentURL = new URL("downloadlimit.html", window.location);
const contentURL = new URL("speedlimit.html", window.location);
contentURL.search = new URLSearchParams({
hashes: hashes.join("|")
hashes: hashes.join("|"),
type: "download",
});
new MochaUI.Window({
id: "downloadLimitPage",

View file

@ -1,249 +0,0 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2019 Thomas Piccirello <thomas.piccirello@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
"use strict";
MochaUI.extend({
addUpLimitSlider: (hashes) => {
if (document.getElementById("uplimitSliderarea")) {
// Get global upload limit
fetch("api/v2/transfer/uploadLimit", {
method: "GET",
cache: "no-store"
})
.then(async (response) => {
if (!response.ok)
return;
const data = await response.text();
let maximum = 500;
const tmp = Number(data);
if (tmp > 0) {
maximum = tmp / 1024.0;
}
else {
if (hashes[0] === "global")
maximum = 10000;
else
maximum = 1000;
}
// Get torrents upload limit
// And create slider
if (hashes[0] === "global") {
let up_limit = maximum;
if (up_limit < 0)
up_limit = 0;
maximum = 10000;
new Slider(document.getElementById("uplimitSliderarea"), document.getElementById("uplimitSliderknob"), {
steps: maximum,
offset: 0,
initialStep: Math.round(up_limit),
onChange: (pos) => {
if (pos > 0) {
document.getElementById("uplimitUpdatevalue").value = pos;
document.getElementById("upLimitUnit").style.visibility = "visible";
}
else {
document.getElementById("uplimitUpdatevalue").value = "∞";
document.getElementById("upLimitUnit").style.visibility = "hidden";
}
}
});
// Set default value
if (up_limit === 0) {
document.getElementById("uplimitUpdatevalue").value = "∞";
document.getElementById("upLimitUnit").style.visibility = "hidden";
}
else {
document.getElementById("uplimitUpdatevalue").value = Math.round(up_limit);
document.getElementById("upLimitUnit").style.visibility = "visible";
}
}
else {
fetch("api/v2/torrents/uploadLimit", {
method: "POST",
body: new URLSearchParams({
hashes: hashes.join("|")
})
})
.then(async (response) => {
if (!response.ok)
return;
const data = await response.json();
let up_limit = data[hashes[0]];
for (const key in data) {
if (up_limit !== data[key]) {
up_limit = 0;
break;
}
}
if (up_limit < 0)
up_limit = 0;
new Slider(document.getElementById("uplimitSliderarea"), document.getElementById("uplimitSliderknob"), {
steps: maximum,
offset: 0,
initialStep: Math.round(up_limit / 1024),
onChange: (pos) => {
if (pos > 0) {
document.getElementById("uplimitUpdatevalue").value = pos;
document.getElementById("upLimitUnit").style.visibility = "visible";
}
else {
document.getElementById("uplimitUpdatevalue").value = "∞";
document.getElementById("upLimitUnit").style.visibility = "hidden";
}
}
});
// Set default value
if (up_limit === 0) {
document.getElementById("uplimitUpdatevalue").value = "∞";
document.getElementById("upLimitUnit").style.visibility = "hidden";
}
else {
document.getElementById("uplimitUpdatevalue").value = Math.round(up_limit / 1024);
document.getElementById("upLimitUnit").style.visibility = "visible";
}
});
}
});
}
},
addDlLimitSlider: (hashes) => {
if (document.getElementById("dllimitSliderarea")) {
// Get global upload limit
fetch("api/v2/transfer/downloadLimit", {
method: "GET",
cache: "no-store"
})
.then(async (response) => {
if (!response.ok)
return;
const data = await response.text();
let maximum = 500;
const tmp = Number(data);
if (tmp > 0) {
maximum = tmp / 1024.0;
}
else {
if (hashes[0] === "global")
maximum = 10000;
else
maximum = 1000;
}
// Get torrents download limit
// And create slider
if (hashes[0] === "global") {
let dl_limit = maximum;
if (dl_limit < 0)
dl_limit = 0;
maximum = 10000;
new Slider(document.getElementById("dllimitSliderarea"), document.getElementById("dllimitSliderknob"), {
steps: maximum,
offset: 0,
initialStep: Math.round(dl_limit),
onChange: (pos) => {
if (pos > 0) {
document.getElementById("dllimitUpdatevalue").value = pos;
document.getElementById("dlLimitUnit").style.visibility = "visible";
}
else {
document.getElementById("dllimitUpdatevalue").value = "∞";
document.getElementById("dlLimitUnit").style.visibility = "hidden";
}
}
});
// Set default value
if (dl_limit === 0) {
document.getElementById("dllimitUpdatevalue").value = "∞";
document.getElementById("dlLimitUnit").style.visibility = "hidden";
}
else {
document.getElementById("dllimitUpdatevalue").value = Math.round(dl_limit);
document.getElementById("dlLimitUnit").style.visibility = "visible";
}
}
else {
fetch("api/v2/torrents/downloadLimit", {
method: "POST",
body: new URLSearchParams({
hashes: hashes.join("|")
})
})
.then(async (response) => {
if (!response.ok)
return;
const data = await response.json();
let dl_limit = data[hashes[0]];
for (const key in data) {
if (dl_limit !== data[key]) {
dl_limit = 0;
break;
}
}
if (dl_limit < 0)
dl_limit = 0;
new Slider(document.getElementById("dllimitSliderarea"), document.getElementById("dllimitSliderknob"), {
steps: maximum,
offset: 0,
initialStep: Math.round(dl_limit / 1024),
onChange: (pos) => {
if (pos > 0) {
document.getElementById("dllimitUpdatevalue").value = pos;
document.getElementById("dlLimitUnit").style.visibility = "visible";
}
else {
document.getElementById("dllimitUpdatevalue").value = "∞";
document.getElementById("dlLimitUnit").style.visibility = "hidden";
}
}
});
// Set default value
if (dl_limit === 0) {
document.getElementById("dllimitUpdatevalue").value = "∞";
document.getElementById("dlLimitUnit").style.visibility = "hidden";
}
else {
document.getElementById("dllimitUpdatevalue").value = Math.round(dl_limit / 1024);
document.getElementById("dlLimitUnit").style.visibility = "visible";
}
});
}
});
}
}
});

View file

@ -0,0 +1,159 @@
<!DOCTYPE html>
<html lang="${LANG}" class="dark">
<head>
<meta charset="UTF-8">
<title>QBT_TR(Speed limit)QBT_TR[CONTEXT=SpeedLimit]</title>
<link rel="stylesheet" href="css/style.css?v=${CACHEID}" type="text/css">
<script src="scripts/localpreferences.js?v=${CACHEID}"></script>
<script src="scripts/color-scheme.js?v=${CACHEID}"></script>
</head>
<body>
<div style="padding-top: 10px; width: 100%; text-align: center; margin: 0 auto; overflow: hidden">
<div class="slider">
<div class="update">
<label id="limitUpdateLabel" for="limitUpdateValue">QBT_TR(Limit:)QBT_TR[CONTEXT=SpeedLimit]</label>
<input type="text" id="limitUpdateValue" size="6" placeholder="∞" style="text-align: center;">
<span id="limitUnit">QBT_TR(KiB/s)QBT_TR[CONTEXT=SpeedLimit]</span>
</div>
<input type="range" id="limitSliderInput" min="0" value="0" style="width: 100%;" aria-label="QBT_TR(Speed limit)QBT_TR[CONTEXT=SpeedLimit]">
</div>
<input type="button" id="applyButton" value="QBT_TR(Apply)QBT_TR[CONTEXT=HttpServer]" onclick="saveLimit()">
</div>
<script>
"use strict";
window.addEventListener("keydown", (event) => {
switch (event.key) {
case "Enter":
event.preventDefault();
document.getElementById("applyButton").click();
break;
case "Escape":
event.preventDefault();
window.parent.qBittorrent.Client.closeFrameWindow(window);
break;
}
});
const params = new URLSearchParams(window.location.search);
const type = params.get("type");
const hashes = params.get("hashes").split("|");
const isGlobal = (hashes[0] === "global");
// Otherwise it's download limit
const isUpload = (type === "upload");
const getLimitMethod = isUpload ? "uploadLimit" : "downloadLimit";
const setLimitMethod = isUpload ? "setUploadLimit" : "setDownloadLimit";
const limitUpdateValue = document.getElementById("limitUpdateValue");
const limitUnit = document.getElementById("limitUnit");
const setLimitUpdateValue = (value) => {
if (value === 0) {
limitUpdateValue.value = "∞";
limitUnit.style.visibility = "hidden";
}
else {
limitUpdateValue.value = value;
limitUnit.style.visibility = "visible";
}
};
const setupSlider = (limit, maximum) => {
const input = document.getElementById("limitSliderInput");
input.max = maximum;
input.value = limit;
input.addEventListener("input", (event) => {
setLimitUpdateValue(Number(event.target.value));
});
// Set default value
setLimitUpdateValue(limit);
};
const saveLimit = () => {
const limit = Number(limitUpdateValue.value) * 1024;
if (isGlobal) {
fetch(`api/v2/transfer/${setLimitMethod}`, {
method: "POST",
body: new URLSearchParams({
limit: limit
})
})
.then((response) => {
if (!response.ok)
return;
window.parent.updateMainData();
window.parent.qBittorrent.Client.closeFrameWindow(window);
});
}
else {
fetch(`api/v2/torrents/${setLimitMethod}`, {
method: "POST",
body: new URLSearchParams({
hashes: hashes.join("|"),
limit: limit
})
})
.then((response) => {
if (!response.ok)
return;
window.parent.qBittorrent.Client.closeFrameWindow(window);
});
}
};
document.getElementById("limitUpdateLabel").textContent =
isUpload
? `QBT_TR(Upload limit:)QBT_TR[CONTEXT=SpeedLimit]`
: `QBT_TR(Download limit:)QBT_TR[CONTEXT=SpeedLimit]`;
fetch(`api/v2/transfer/${getLimitMethod}`, {
method: "GET",
cache: "no-store"
})
.then(async (response) => {
if (!response.ok)
return;
const data = await response.text();
const globalLimit = Math.max((Number(data) / 1024), 0);
// Get torrents download limit
// And create slider
if (isGlobal) {
setupSlider(globalLimit, 10000);
}
else {
fetch(`api/v2/torrents/${getLimitMethod}`, {
method: "POST",
body: new URLSearchParams({
hashes: hashes.join("|")
})
})
.then(async (response) => {
if (!response.ok)
return;
const data = await response.json();
const firstLimit = Math.max(data[hashes[0]], 0);
const isAllFirstLimit = Object.values(data).every(value => value === firstLimit);
const limit = isAllFirstLimit ? Math.round(firstLimit / 1024) : 0;
setupSlider(limit, ((globalLimit > 0) ? globalLimit : 1000));
});
}
});
limitUpdateValue.focus();
</script>
</body>
</html>

View file

@ -1,90 +0,0 @@
<!DOCTYPE html>
<html lang="${LANG}" class="dark">
<head>
<meta charset="UTF-8">
<title>QBT_TR(Torrent Upload Speed Limiting)QBT_TR[CONTEXT=TransferListWidget]</title>
<link rel="stylesheet" href="css/style.css?v=${CACHEID}" type="text/css">
<script src="scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
<script src="scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
<script src="scripts/lib/mocha.min.js"></script>
<script src="scripts/localpreferences.js?v=${CACHEID}"></script>
<script src="scripts/color-scheme.js?v=${CACHEID}"></script>
<script src="scripts/speedslider.js?v=${CACHEID}"></script>
</head>
<body>
<div style="padding-top: 10px; width: 100%; text-align: center; margin: 0 auto; overflow: hidden">
<div id="uplimitSlider" class="slider">
<div id="uplimitUpdate" class="update">
<label for="uplimitUpdatevalue">QBT_TR(Upload limit:)QBT_TR[CONTEXT=PropertiesWidget]</label>
<input type="text" id="uplimitUpdatevalue" size="6" placeholder="∞" style="text-align: center;">
<span id="upLimitUnit">QBT_TR(KiB/s)QBT_TR[CONTEXT=SpeedLimitDialog]</span>
</div>
<div class="sliderWrapper">
<div id="uplimitSliderknob" class="sliderknob"></div>
<div id="uplimitSliderarea" class="sliderarea"></div>
</div>
<div class="clear"></div>
</div>
<input type="button" id="applyButton" value="QBT_TR(Apply)QBT_TR[CONTEXT=HttpServer]" onclick="setUpLimit()">
</div>
<script>
"use strict";
window.addEventListener("keydown", (event) => {
switch (event.key) {
case "Enter":
event.preventDefault();
document.getElementById("applyButton").click();
break;
case "Escape":
event.preventDefault();
window.parent.qBittorrent.Client.closeFrameWindow(window);
break;
}
});
const hashes = new URLSearchParams(window.location.search).get("hashes").split("|");
const setUpLimit = () => {
const limit = Number(document.getElementById("uplimitUpdatevalue").value) * 1024;
if (hashes[0] === "global") {
fetch("api/v2/transfer/setUploadLimit", {
method: "POST",
body: new URLSearchParams({
limit: limit
})
})
.then((response) => {
if (!response.ok)
return;
window.parent.updateMainData();
window.parent.qBittorrent.Client.closeFrameWindow(window);
});
}
else {
fetch("api/v2/torrents/setUploadLimit", {
method: "POST",
body: new URLSearchParams({
hashes: hashes.join("|"),
limit: limit
})
})
.then((response) => {
if (!response.ok)
return;
window.parent.qBittorrent.Client.closeFrameWindow(window);
});
}
};
document.getElementById("uplimitUpdatevalue").focus();
MochaUI.addUpLimitSlider(hashes);
</script>
</body>
</html>

View file

@ -16,7 +16,6 @@
<file>private/css/vanillaSelectBox.css</file>
<file>private/css/Window.css</file>
<file>private/download.html</file>
<file>private/downloadlimit.html</file>
<file>private/editfeedurl.html</file>
<file>private/edittracker.html</file>
<file>private/editwebseed.html</file>
@ -329,7 +328,6 @@
<file>private/images/help-contents.svg</file>
<file>private/images/insert-link.svg</file>
<file>private/images/ip-blocked.svg</file>
<file>private/images/knob.gif</file>
<file>private/images/L.gif</file>
<file>private/images/list-add.svg</file>
<file>private/images/list-remove.svg</file>
@ -356,7 +354,6 @@
<file>private/images/reannounce.svg</file>
<file>private/images/regex.svg</file>
<file>private/images/set-location.svg</file>
<file>private/images/slider-area.gif</file>
<file>private/images/slow.svg</file>
<file>private/images/slow_off.svg</file>
<file>private/images/spacer.gif</file>
@ -419,11 +416,10 @@
<file>private/scripts/prop-webseeds.js</file>
<file>private/scripts/rename-files.js</file>
<file>private/scripts/search.js</file>
<file>private/scripts/speedslider.js</file>
<file>private/setlocation.html</file>
<file>private/shareratio.html</file>
<file>private/speedlimit.html</file>
<file>private/upload.html</file>
<file>private/uploadlimit.html</file>
<file>private/views/about.html</file>
<file>private/views/aboutToolbar.html</file>
<file>private/views/confirmAutoTMM.html</file>