2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2014 Gabriele <pmzqla.git@gmail.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * In addition, as a special exception, the copyright holders give permission to
20 * link this program with the OpenSSL project's "OpenSSL" library (or with
21 * modified versions of it that use the same license as the "OpenSSL" library),
22 * and distribute the linked executables. You must obey the GNU General Public
23 * License in all respects for all of the code used other than "OpenSSL". If you
24 * modify file(s), you may extend this exception to your version of the file(s),
25 * but you are not obligated to do so. If you do not wish to do so, delete this
26 * exception statement from your version.
31 window
.qBittorrent
??= {};
32 window
.qBittorrent
.Misc
??= (() => {
33 const exports
= () => {
35 friendlyUnit
: friendlyUnit
,
36 friendlyDuration
: friendlyDuration
,
37 friendlyPercentage
: friendlyPercentage
,
38 friendlyFloat
: friendlyFloat
,
39 parseHtmlLinks
: parseHtmlLinks
,
40 parseVersion
: parseVersion
,
41 escapeHtml
: escapeHtml
,
42 naturalSortCollator
: naturalSortCollator
,
44 toFixedPointString
: toFixedPointString
,
45 containsAllTerms
: containsAllTerms
,
48 FILTER_INPUT_DELAY
: 400,
54 * JS counterpart of the function in src/misc.cpp
56 const friendlyUnit = function(value
, isSpeed
) {
58 "QBT_TR(B)QBT_TR[CONTEXT=misc]",
59 "QBT_TR(KiB)QBT_TR[CONTEXT=misc]",
60 "QBT_TR(MiB)QBT_TR[CONTEXT=misc]",
61 "QBT_TR(GiB)QBT_TR[CONTEXT=misc]",
62 "QBT_TR(TiB)QBT_TR[CONTEXT=misc]",
63 "QBT_TR(PiB)QBT_TR[CONTEXT=misc]",
64 "QBT_TR(EiB)QBT_TR[CONTEXT=misc]"
67 if ((value
=== undefined) || (value
=== null) || (value
< 0))
68 return "QBT_TR(Unknown)QBT_TR[CONTEXT=misc]";
71 while ((value
>= 1024.0) && (i
< 6)) {
76 function friendlyUnitPrecision(sizeUnit
) {
77 if (sizeUnit
<= 2) // KiB, MiB
79 else if (sizeUnit
=== 3) // GiB
87 ret
= value
+ " " + units
[i
];
90 const precision
= friendlyUnitPrecision(i
);
91 const offset
= Math
.pow(10, precision
);
93 ret
= (Math
.floor(offset
* value
) / offset
).toFixed(precision
) + " " + units
[i
];
97 ret
+= "QBT_TR(/s)QBT_TR[CONTEXT=misc]";
102 * JS counterpart of the function in src/misc.cpp
104 const friendlyDuration = function(seconds
, maxCap
= -1) {
105 if ((seconds
< 0) || ((seconds
>= maxCap
) && (maxCap
>= 0)))
110 return "QBT_TR(< 1m)QBT_TR[CONTEXT=misc]";
111 let minutes
= seconds
/ 60;
113 return "QBT_TR(%1m)QBT_TR[CONTEXT=misc]".replace("%1", Math
.floor(minutes
));
114 let hours
= minutes
/ 60;
117 return "QBT_TR(%1h %2m)QBT_TR[CONTEXT=misc]".replace("%1", Math
.floor(hours
)).replace("%2", Math
.floor(minutes
));
118 let days
= hours
/ 24;
121 return "QBT_TR(%1d %2h)QBT_TR[CONTEXT=misc]".replace("%1", Math
.floor(days
)).replace("%2", Math
.floor(hours
));
122 const years
= days
/ 365;
124 return "QBT_TR(%1y %2d)QBT_TR[CONTEXT=misc]".replace("%1", Math
.floor(years
)).replace("%2", Math
.floor(days
));
127 const friendlyPercentage = function(value
) {
128 let percentage
= (value
* 100).round(1);
129 if (isNaN(percentage
) || (percentage
< 0))
131 if (percentage
> 100)
133 return percentage
.toFixed(1) + "%";
136 const friendlyFloat = function(value
, precision
) {
137 return parseFloat(value
).toFixed(precision
);
141 * JS counterpart of the function in src/misc.cpp
143 const parseHtmlLinks = function(text
) {
144 const exp
= /(\b(https?|ftp|file):\/\/[-\w+&@#/%?=~|!:,.;]*[-\w
+&@#/%=~|])/gi;
145 return text
.replace(exp
, "<a target='_blank' rel='noopener noreferrer' href='$1'>$1</a>");
148 const parseVersion = function(versionString
) {
153 if (typeof versionString
!== "string")
156 const tryToNumber
= (str
) => {
157 const num
= Number(str
);
158 return (isNaN(num
) ? str
: num
);
161 const ver
= versionString
.split(".", 4).map(val
=> tryToNumber(val
));
171 const escapeHtml
= (() => {
172 const div
= document
.createElement("div");
174 div
.textContent
= str
;
175 return div
.innerHTML
;
179 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator/Collator#parameters
180 const naturalSortCollator
= new Intl
.Collator(undefined, { numeric
: true, usage
: "sort" });
182 const safeTrim = function(value
) {
187 if (e
instanceof TypeError
)
193 const toFixedPointString = function(number
, digits
) {
194 // Do not round up number
195 const power
= Math
.pow(10, digits
);
196 return (Math
.floor(power
* number
) / power
).toFixed(digits
);
201 * @param {String} text the text to search
202 * @param {Array<String>} terms terms to search for within the text
203 * @returns {Boolean} true if all terms match the text, false otherwise
205 const containsAllTerms = function(text
, terms
) {
206 const textToSearch
= text
.toLowerCase();
207 return terms
.every((term
) => {
208 const isTermRequired
= (term
[0] === "+");
209 const isTermExcluded
= (term
[0] === "-");
210 if (isTermRequired
|| isTermExcluded
) {
212 if (term
.length
=== 1)
215 term
= term
.substring(1);
218 const textContainsTerm
= (textToSearch
.indexOf(term
) !== -1);
219 return isTermExcluded
? !textContainsTerm
: textContainsTerm
;
223 const sleep
= (ms
) => {
224 return new Promise((resolve
) => {
225 setTimeout(resolve
, ms
);
231 Object
.freeze(window
.qBittorrent
.Misc
);