mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2026-01-03 14:12:30 -06:00
WebUI: replace rounding function from MooTools
The `round()` returning floating point number is not a good idea. This is due to floating point representation is imprecise and sometimes it cannot faithfully represent a number, for example `0.09 + 0.01 !== 0.1 `. Therefore, it should be avoided and/or utilize other function to achieve the goal. Also, improve `window.qBittorrent.Misc.toFixedPointString()` and add test cases. PR #22281.
This commit is contained in:
@@ -1231,9 +1231,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
||||
// progress
|
||||
this.columns["progress"].updateTd = function(td, row) {
|
||||
const progress = this.getRowValue(row);
|
||||
let progressFormatted = (progress * 100).round(1);
|
||||
if ((progressFormatted === 100.0) && (progress !== 1.0))
|
||||
progressFormatted = 99.9;
|
||||
const progressFormatted = window.qBittorrent.Misc.toFixedPointString((progress * 100), 1);
|
||||
|
||||
const div = td.firstElementChild;
|
||||
if (div !== null) {
|
||||
@@ -1782,10 +1780,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
||||
// progress
|
||||
this.columns["progress"].updateTd = function(td, row) {
|
||||
const progress = this.getRowValue(row);
|
||||
let progressFormatted = (progress * 100).round(1);
|
||||
if ((progressFormatted === 100.0) && (progress !== 1.0))
|
||||
progressFormatted = 99.9;
|
||||
progressFormatted += "%";
|
||||
const progressFormatted = `${window.qBittorrent.Misc.toFixedPointString((progress * 100), 1)}%`;
|
||||
td.textContent = progressFormatted;
|
||||
td.title = progressFormatted;
|
||||
};
|
||||
|
||||
@@ -92,6 +92,9 @@ window.qBittorrent.Misc ??= (() => {
|
||||
* JS counterpart of the function in src/misc.cpp
|
||||
*/
|
||||
const friendlyUnit = (value, isSpeed) => {
|
||||
if ((value === undefined) || (value === null) || Number.isNaN(value) || (value < 0))
|
||||
return "QBT_TR(Unknown)QBT_TR[CONTEXT=misc]";
|
||||
|
||||
const units = [
|
||||
"QBT_TR(B)QBT_TR[CONTEXT=misc]",
|
||||
"QBT_TR(KiB)QBT_TR[CONTEXT=misc]",
|
||||
@@ -102,15 +105,6 @@ window.qBittorrent.Misc ??= (() => {
|
||||
"QBT_TR(EiB)QBT_TR[CONTEXT=misc]"
|
||||
];
|
||||
|
||||
if ((value === undefined) || (value === null) || (value < 0))
|
||||
return "QBT_TR(Unknown)QBT_TR[CONTEXT=misc]";
|
||||
|
||||
let i = 0;
|
||||
while ((value >= 1024.0) && (i < 6)) {
|
||||
value /= 1024.0;
|
||||
++i;
|
||||
}
|
||||
|
||||
const friendlyUnitPrecision = (sizeUnit) => {
|
||||
if (sizeUnit <= 2) // KiB, MiB
|
||||
return 1;
|
||||
@@ -120,15 +114,20 @@ window.qBittorrent.Misc ??= (() => {
|
||||
return 3;
|
||||
};
|
||||
|
||||
let i = 0;
|
||||
while ((value >= 1024) && (i < 6)) {
|
||||
value /= 1024;
|
||||
++i;
|
||||
}
|
||||
|
||||
let ret;
|
||||
if (i === 0) {
|
||||
ret = `${value} ${units[i]}`;
|
||||
}
|
||||
else {
|
||||
const precision = friendlyUnitPrecision(i);
|
||||
const offset = Math.pow(10, precision);
|
||||
// Don't round up
|
||||
ret = `${(Math.floor(offset * value) / offset).toFixed(precision)} ${units[i]}`;
|
||||
ret = `${toFixedPointString(value, precision)} ${units[i]}`;
|
||||
}
|
||||
|
||||
if (isSpeed)
|
||||
@@ -163,12 +162,12 @@ window.qBittorrent.Misc ??= (() => {
|
||||
};
|
||||
|
||||
const friendlyPercentage = (value) => {
|
||||
let percentage = (value * 100).round(1);
|
||||
let percentage = value * 100;
|
||||
if (Number.isNaN(percentage) || (percentage < 0))
|
||||
percentage = 0;
|
||||
if (percentage > 100)
|
||||
percentage = 100;
|
||||
return `${percentage.toFixed(1)}%`;
|
||||
return `${toFixedPointString(percentage, 1)}%`;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -225,13 +224,27 @@ window.qBittorrent.Misc ??= (() => {
|
||||
};
|
||||
|
||||
const toFixedPointString = (number, digits) => {
|
||||
// Do not round up number
|
||||
const power = Math.pow(10, digits);
|
||||
return (Math.floor(power * number) / power).toFixed(digits);
|
||||
if (Number.isNaN(number))
|
||||
return number.toString();
|
||||
|
||||
const sign = (number < 0) ? "-" : "";
|
||||
// Do not round up `number`
|
||||
// Small floating point numbers are imprecise, thus process as a String
|
||||
const tmp = Math.trunc(`${Math.abs(number)}e${digits}`).toString();
|
||||
if (digits <= 0) {
|
||||
return (tmp === "0") ? tmp : `${sign}${tmp}`;
|
||||
}
|
||||
else if (digits < tmp.length) {
|
||||
const idx = tmp.length - digits;
|
||||
return `${sign}${tmp.slice(0, idx)}.${tmp.slice(idx)}`;
|
||||
}
|
||||
else {
|
||||
const zeros = "0".repeat(digits - tmp.length);
|
||||
return `${sign}0.${zeros}${tmp}`;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {String} text the text to search
|
||||
* @param {Array<String>} terms terms to search for within the text
|
||||
* @returns {Boolean} true if all terms match the text, false otherwise
|
||||
|
||||
@@ -116,13 +116,13 @@ window.qBittorrent.ProgressBar ??= (() => {
|
||||
}
|
||||
|
||||
function ProgressBar_setValue(value) {
|
||||
value = parseFloat(value);
|
||||
value = Number(value);
|
||||
if (Number.isNaN(value))
|
||||
value = 0;
|
||||
value = Math.min(Math.max(value, 0), 100);
|
||||
this.vals.value = value;
|
||||
|
||||
const displayedValue = `${value.round(1).toFixed(1)}%`;
|
||||
const displayedValue = `${window.qBittorrent.Misc.toFixedPointString(value, 1)}%`;
|
||||
this.vals.dark.textContent = displayedValue;
|
||||
this.vals.light.textContent = displayedValue;
|
||||
|
||||
|
||||
@@ -383,25 +383,18 @@ window.qBittorrent.PropFiles ??= (() => {
|
||||
is_seed = (files.length > 0) ? files[0].is_seed : true;
|
||||
|
||||
const rows = files.map((file, index) => {
|
||||
let progress = (file.progress * 100).round(1);
|
||||
if ((progress === 100) && (file.progress < 1))
|
||||
progress = 99.9;
|
||||
|
||||
const ignore = (file.priority === FilePriority.Ignored);
|
||||
const checked = (ignore ? TriState.Unchecked : TriState.Checked);
|
||||
const remaining = (ignore ? 0 : (file.size * (1.0 - file.progress)));
|
||||
const row = {
|
||||
fileId: index,
|
||||
checked: checked,
|
||||
checked: (ignore ? TriState.Unchecked : TriState.Checked),
|
||||
fileName: file.name,
|
||||
name: window.qBittorrent.Filesystem.fileName(file.name),
|
||||
size: file.size,
|
||||
progress: progress,
|
||||
progress: window.qBittorrent.Misc.toFixedPointString((file.progress * 100), 1),
|
||||
priority: normalizePriority(file.priority),
|
||||
remaining: remaining,
|
||||
remaining: (ignore ? 0 : (file.size * (1 - file.progress))),
|
||||
availability: file.availability
|
||||
};
|
||||
|
||||
return row;
|
||||
});
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ MochaUI.extend({
|
||||
new Slider($("uplimitSliderarea"), $("uplimitSliderknob"), {
|
||||
steps: maximum,
|
||||
offset: 0,
|
||||
initialStep: up_limit.round(),
|
||||
initialStep: Math.round(up_limit),
|
||||
onChange: (pos) => {
|
||||
if (pos > 0) {
|
||||
$("uplimitUpdatevalue").value = pos;
|
||||
@@ -82,7 +82,7 @@ MochaUI.extend({
|
||||
$("upLimitUnit").style.visibility = "hidden";
|
||||
}
|
||||
else {
|
||||
$("uplimitUpdatevalue").value = up_limit.round();
|
||||
$("uplimitUpdatevalue").value = Math.round(up_limit);
|
||||
$("upLimitUnit").style.visibility = "visible";
|
||||
}
|
||||
}
|
||||
@@ -111,7 +111,7 @@ MochaUI.extend({
|
||||
new Slider($("uplimitSliderarea"), $("uplimitSliderknob"), {
|
||||
steps: maximum,
|
||||
offset: 0,
|
||||
initialStep: (up_limit / 1024.0).round(),
|
||||
initialStep: Math.round(up_limit / 1024),
|
||||
onChange: (pos) => {
|
||||
if (pos > 0) {
|
||||
$("uplimitUpdatevalue").value = pos;
|
||||
@@ -129,7 +129,7 @@ MochaUI.extend({
|
||||
$("upLimitUnit").style.visibility = "hidden";
|
||||
}
|
||||
else {
|
||||
$("uplimitUpdatevalue").value = (up_limit / 1024.0).round();
|
||||
$("uplimitUpdatevalue").value = Math.round(up_limit / 1024);
|
||||
$("upLimitUnit").style.visibility = "visible";
|
||||
}
|
||||
});
|
||||
@@ -173,7 +173,7 @@ MochaUI.extend({
|
||||
new Slider($("dllimitSliderarea"), $("dllimitSliderknob"), {
|
||||
steps: maximum,
|
||||
offset: 0,
|
||||
initialStep: dl_limit.round(),
|
||||
initialStep: Math.round(dl_limit),
|
||||
onChange: (pos) => {
|
||||
if (pos > 0) {
|
||||
$("dllimitUpdatevalue").value = pos;
|
||||
@@ -191,7 +191,7 @@ MochaUI.extend({
|
||||
$("dlLimitUnit").style.visibility = "hidden";
|
||||
}
|
||||
else {
|
||||
$("dllimitUpdatevalue").value = dl_limit.round();
|
||||
$("dllimitUpdatevalue").value = Math.round(dl_limit);
|
||||
$("dlLimitUnit").style.visibility = "visible";
|
||||
}
|
||||
}
|
||||
@@ -220,7 +220,7 @@ MochaUI.extend({
|
||||
new Slider($("dllimitSliderarea"), $("dllimitSliderknob"), {
|
||||
steps: maximum,
|
||||
offset: 0,
|
||||
initialStep: (dl_limit / 1024.0).round(),
|
||||
initialStep: Math.round(dl_limit / 1024),
|
||||
onChange: (pos) => {
|
||||
if (pos > 0) {
|
||||
$("dllimitUpdatevalue").value = pos;
|
||||
@@ -238,7 +238,7 @@ MochaUI.extend({
|
||||
$("dlLimitUnit").style.visibility = "hidden";
|
||||
}
|
||||
else {
|
||||
$("dllimitUpdatevalue").value = (dl_limit / 1024.0).round();
|
||||
$("dllimitUpdatevalue").value = Math.round(dl_limit / 1024);
|
||||
$("dlLimitUnit").style.visibility = "visible";
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user