Browse Source

WebUI: make API locale independet

Sizes are now given in bytes.
Dates are Unix timestamps and converted to ISO 8601 in the web UI.
Numbers are not converted to strings.
-1 is returned for undefined values.

Some keys have been splitted:

Torrent list (json/torrents)
 * num_seeds: Torrent seeds connected to
 * num_complete: Torrent seeds in the swarm
 * num_leechs: Torrent leechers connected to
 * num_incomplete: Torrent leechers in the swarm

Torrent generic properties (propertiesGeneral/hash)
 * total_uploaded: Total data uploaded
 * total_uploaded_session: Total data uploaded this session
 * total_downloaded: Total data dowloaded
 * total_downloaded_session: Total data downloaded this session
 * time_elapsed: Torrent elapsed time
 * seeding_time: Torrent elapsed time while complete
 * nb_connections: Torrent connection count
 * nb_connections_limit: Torrent connection count limit

Global transfer info (json/transferInfo)
 * dl_info_speed: Global downalod rate
 * dl_info_data: Data downloaded this session
 * up_info_speed: Global upload rate
 * up_info_data: Data uploaded this session

Closes #1524.
adaptive-webui-19844
Gabriele 10 years ago
parent
commit
aedf579d77
  1. 9
      src/qtlibtorrent/qtorrenthandle.cpp
  2. 1
      src/qtlibtorrent/qtorrenthandle.h
  3. 100
      src/webui/btjson.cpp
  4. 1
      src/webui/webui.qrc
  5. 1
      src/webui/www/private/index.html
  6. 2
      src/webui/www/public/prop-files.html
  7. 33
      src/webui/www/public/prop-general.html
  8. 31
      src/webui/www/public/scripts/client.js
  9. 78
      src/webui/www/public/scripts/misc.js

9
src/qtlibtorrent/qtorrenthandle.cpp

@ -103,6 +103,15 @@ QString QTorrentHandle::creation_date() const { @@ -103,6 +103,15 @@ QString QTorrentHandle::creation_date() const {
return t ? misc::toQString(*t) : "";
}
qlonglong QTorrentHandle::creation_date_unix() const {
#if LIBTORRENT_VERSION_NUM < 10000
boost::optional<time_t> t = torrent_handle::get_torrent_info().creation_date();
#else
boost::optional<time_t> t = torrent_handle::torrent_file()->creation_date();
#endif
return t ? *t : -1;
}
QString QTorrentHandle::current_tracker() const {
return misc::toQString(status(0x0).current_tracker);
}

1
src/qtlibtorrent/qtorrenthandle.h

@ -84,6 +84,7 @@ public: @@ -84,6 +84,7 @@ public:
bool is_checking() const;
bool is_sequential_download() const;
QString creation_date() const;
qlonglong creation_date_unix() const;
bool priv() const;
bool first_last_piece_first() const;
QString root_path() const;

100
src/webui/btjson.cpp

@ -29,7 +29,6 @@ @@ -29,7 +29,6 @@
*/
#include "btjson.h"
#include "misc.h"
#include "fs_utils.h"
#include "qbtsession.h"
#include "torrentpersistentdata.h"
@ -89,7 +88,9 @@ static const char KEY_TORRENT_DLSPEED[] = "dlspeed"; @@ -89,7 +88,9 @@ static const char KEY_TORRENT_DLSPEED[] = "dlspeed";
static const char KEY_TORRENT_UPSPEED[] = "upspeed";
static const char KEY_TORRENT_PRIORITY[] = "priority";
static const char KEY_TORRENT_SEEDS[] = "num_seeds";
static const char KEY_TORRENT_NUM_COMPLETE[] = "num_complete";
static const char KEY_TORRENT_LEECHS[] = "num_leechs";
static const char KEY_TORRENT_NUM_INCOMPLETE[] = "num_incomplete";
static const char KEY_TORRENT_RATIO[] = "ratio";
static const char KEY_TORRENT_ETA[] = "eta";
static const char KEY_TORRENT_STATE[] = "state";
@ -107,11 +108,15 @@ static const char KEY_PROP_PIECE_SIZE[] = "piece_size"; @@ -107,11 +108,15 @@ static const char KEY_PROP_PIECE_SIZE[] = "piece_size";
static const char KEY_PROP_COMMENT[] = "comment";
static const char KEY_PROP_WASTED[] = "total_wasted";
static const char KEY_PROP_UPLOADED[] = "total_uploaded";
static const char KEY_PROP_UPLOADED_SESSION[] = "total_uploaded_session";
static const char KEY_PROP_DOWNLOADED[] = "total_downloaded";
static const char KEY_PROP_DOWNLOADED_SESSION[] = "total_downloaded_session";
static const char KEY_PROP_UP_LIMIT[] = "up_limit";
static const char KEY_PROP_DL_LIMIT[] = "dl_limit";
static const char KEY_PROP_TIME_ELAPSED[] = "time_elapsed";
static const char KEY_PROP_SEEDING_TIME[] = "seeding_time";
static const char KEY_PROP_CONNECT_COUNT[] = "nb_connections";
static const char KEY_PROP_CONNECT_COUNT_LIMIT[] = "nb_connections_limit";
static const char KEY_PROP_RATIO[] = "share_ratio";
// File keys
@ -122,8 +127,10 @@ static const char KEY_FILE_PRIORITY[] = "priority"; @@ -122,8 +127,10 @@ static const char KEY_FILE_PRIORITY[] = "priority";
static const char KEY_FILE_IS_SEED[] = "is_seed";
// TransferInfo keys
static const char KEY_TRANSFER_DLSPEED[] = "dl_info";
static const char KEY_TRANSFER_UPSPEED[] = "up_info";
static const char KEY_TRANSFER_DLSPEED[] = "dl_info_speed";
static const char KEY_TRANSFER_DLDATA[] = "dl_info_data";
static const char KEY_TRANSFER_UPSPEED[] = "up_info_speed";
static const char KEY_TRANSFER_UPDATA[] = "up_info_data";
static QVariantMap toMap(const QTorrentHandle& h)
{
@ -132,25 +139,21 @@ static QVariantMap toMap(const QTorrentHandle& h) @@ -132,25 +139,21 @@ static QVariantMap toMap(const QTorrentHandle& h)
QVariantMap ret;
ret[KEY_TORRENT_HASH] = h.hash();
ret[KEY_TORRENT_NAME] = h.name();
ret[KEY_TORRENT_SIZE] = misc::friendlyUnit(status.total_wanted, false, true); // FIXME: Should pass as Number, not formatted String (for sorting).
ret[KEY_TORRENT_PROGRESS] = (double)h.progress(status);
ret[KEY_TORRENT_DLSPEED] = misc::friendlyUnit(status.download_payload_rate, true, true); // FIXME: Should be passed as a Number
ret[KEY_TORRENT_UPSPEED] = misc::friendlyUnit(status.upload_payload_rate, true, true); // FIXME: Should be passed as a Number
ret[KEY_TORRENT_SIZE] = static_cast<qlonglong>(status.total_wanted);
ret[KEY_TORRENT_PROGRESS] = h.progress(status);
ret[KEY_TORRENT_DLSPEED] = status.download_payload_rate;
ret[KEY_TORRENT_UPSPEED] = status.upload_payload_rate;
if (QBtSession::instance()->isQueueingEnabled() && h.queue_position(status) >= 0)
ret[KEY_TORRENT_PRIORITY] = QString::number(h.queue_position(status));
ret[KEY_TORRENT_PRIORITY] = h.queue_position(status);
else
ret[KEY_TORRENT_PRIORITY] = "*";
QString seeds = QString::number(status.num_seeds);
if (status.num_complete > 0)
seeds += " ("+QString::number(status.num_complete)+")";
ret[KEY_TORRENT_SEEDS] = seeds;
QString leechs = QString::number(status.num_peers - status.num_seeds);
if (status.num_incomplete > 0)
leechs += " ("+QString::number(status.num_incomplete)+")";
ret[KEY_TORRENT_LEECHS] = leechs;
ret[KEY_TORRENT_PRIORITY] = -1;
ret[KEY_TORRENT_SEEDS] = status.num_seeds;
ret[KEY_TORRENT_NUM_COMPLETE] = status.num_complete;
ret[KEY_TORRENT_LEECHS] = status.num_peers - status.num_seeds;
ret[KEY_TORRENT_NUM_INCOMPLETE] = status.num_incomplete;
const qreal ratio = QBtSession::instance()->getRealRatio(status);
ret[KEY_TORRENT_RATIO] = (ratio > 100.) ? QString::fromUtf8("") : misc::accurateDoubleToString(ratio, 1, false);
QString eta;
ret[KEY_TORRENT_RATIO] = (ratio > 100.) ? -1 : ratio;
qulonglong eta = 0;
QString state;
if (h.is_paused(status)) {
if (h.has_error(status))
@ -175,14 +178,14 @@ static QVariantMap toMap(const QTorrentHandle& h) @@ -175,14 +178,14 @@ static QVariantMap toMap(const QTorrentHandle& h)
case torrent_status::downloading:
case torrent_status::downloading_metadata:
state = status.download_payload_rate > 0 ? "downloading" : "stalledDL";
eta = misc::userFriendlyDuration(QBtSession::instance()->getETA(h.hash(), status));
eta = QBtSession::instance()->getETA(h.hash(), status);
break;
default:
qWarning("Unrecognized torrent status, should not happen!!! status was %d", h.state());
}
}
}
ret[KEY_TORRENT_ETA] = eta.isEmpty() ? QString::fromUtf8("") : eta;
ret[KEY_TORRENT_ETA] = eta ? eta : MAX_ETA;
ret[KEY_TORRENT_STATE] = state;
return ret;
@ -199,9 +202,11 @@ static QVariantMap toMap(const QTorrentHandle& h) @@ -199,9 +202,11 @@ static QVariantMap toMap(const QTorrentHandle& h)
* - "progress: Torrent progress
* - "dlspeed": Torrent download speed
* - "upspeed": Torrent upload speed
* - "priority": Torrent priority ('*' if queuing is disabled)
* - "num_seeds": Torrent seed count
* - "num_leechs": Torrent leecher count
* - "priority": Torrent priority (-1 if queuing is disabled)
* - "num_seeds": Torrent seeds connected to
* - "num_complete": Torrent seeds in the swarm
* - "num_leechs": Torrent leechers connected to
* - "num_incomplete": Torrent leechers in the swarm
* - "ratio": Torrent share ratio
* - "eta": Torrent ETA
* - "state": Torrent state
@ -252,7 +257,7 @@ QByteArray btjson::getTrackersForTorrent(const QString& hash) @@ -252,7 +257,7 @@ QByteArray btjson::getTrackersForTorrent(const QString& hash)
status = it->fails > 0 ? tr("Not working") : tr("Not contacted yet");
}
tracker_dict[KEY_TRACKER_STATUS] = status;
tracker_dict[KEY_TRACKER_PEERS] = QString::number(trackers_data.value(tracker_url, TrackerInfos(tracker_url)).num_peers);
tracker_dict[KEY_TRACKER_PEERS] = static_cast<qulonglong>(trackers_data.value(tracker_url, TrackerInfos(tracker_url)).num_peers);
tracker_dict[KEY_TRACKER_MSG] = data.last_message.trimmed();
tracker_list.append(tracker_dict);
@ -276,11 +281,15 @@ QByteArray btjson::getTrackersForTorrent(const QString& hash) @@ -276,11 +281,15 @@ QByteArray btjson::getTrackersForTorrent(const QString& hash)
* - "comment": Torrent comment
* - "total_wasted": Total data wasted for torrent
* - "total_uploaded": Total data uploaded for torrent
* - "total_uploaded_session": Total data uploaded this session
* - "total_downloaded": Total data uploaded for torrent
* - "total_downloaded_session": Total data downloaded this session
* - "up_limit": Torrent upload limit
* - "dl_limit": Torrent download limit
* - "time_elapsed": Torrent elapsed time
* - "seeding_time": Torrent elapsed time while complete
* - "nb_connections": Torrent connection count
* - "nb_connections_limit": Torrent connection count limit
* - "share_ratio": Torrent share ratio
*/
QByteArray btjson::getPropertiesForTorrent(const QString& hash)
@ -298,21 +307,22 @@ QByteArray btjson::getPropertiesForTorrent(const QString& hash) @@ -298,21 +307,22 @@ QByteArray btjson::getPropertiesForTorrent(const QString& hash)
if (save_path.isEmpty())
save_path = fsutils::toNativePath(h.save_path());
data[KEY_PROP_SAVE_PATH] = save_path;
data[KEY_PROP_CREATION_DATE] = h.creation_date();
data[KEY_PROP_PIECE_SIZE] = misc::friendlyUnit(h.piece_length(), false, true);
data[KEY_PROP_CREATION_DATE] = h.creation_date_unix();
data[KEY_PROP_PIECE_SIZE] = static_cast<qlonglong>(h.piece_length());
data[KEY_PROP_COMMENT] = h.comment();
data[KEY_PROP_WASTED] = misc::friendlyUnit(status.total_failed_bytes + status.total_redundant_bytes, false, true);
data[KEY_PROP_UPLOADED] = QString(misc::friendlyUnit(status.all_time_upload, false, true) + " (" + misc::friendlyUnit(status.total_payload_upload, false, true) + " " + tr("this session") + ")");
data[KEY_PROP_DOWNLOADED] = QString(misc::friendlyUnit(status.all_time_download, false, true) + " (" + misc::friendlyUnit(status.total_payload_download, false, true) + " " + tr("this session") + ")");
data[KEY_PROP_UP_LIMIT] = h.upload_limit() <= 0 ? QString::fromUtf8("") : misc::friendlyUnit(h.upload_limit(), true, true);
data[KEY_PROP_DL_LIMIT] = h.download_limit() <= 0 ? QString::fromUtf8("") : misc::friendlyUnit(h.download_limit(), true, true);
QString elapsed_txt = misc::userFriendlyDuration(status.active_time);
if (h.is_seed(status))
elapsed_txt += " ("+tr("Seeded for %1", "e.g. Seeded for 3m10s").arg(misc::userFriendlyDuration(status.seeding_time))+")";
data[KEY_PROP_TIME_ELAPSED] = elapsed_txt;
data[KEY_PROP_CONNECT_COUNT] = QString(QString::number(status.num_connections) + " (" + tr("%1 max", "e.g. 10 max").arg(QString::number(status.connections_limit)) + ")");
data[KEY_PROP_WASTED] = static_cast<qlonglong>(status.total_failed_bytes + status.total_redundant_bytes);
data[KEY_PROP_UPLOADED] = static_cast<qlonglong>(status.all_time_upload);
data[KEY_PROP_UPLOADED_SESSION] = static_cast<qlonglong>(status.total_payload_upload);
data[KEY_PROP_DOWNLOADED] = static_cast<qlonglong>(status.all_time_download);
data[KEY_PROP_DOWNLOADED_SESSION] = static_cast<qlonglong>(status.total_payload_download);
data[KEY_PROP_UP_LIMIT] = h.upload_limit() <= 0 ? -1 : h.upload_limit();
data[KEY_PROP_DL_LIMIT] = h.download_limit() <= 0 ? -1 : h.download_limit();
data[KEY_PROP_TIME_ELAPSED] = status.active_time;
data[KEY_PROP_SEEDING_TIME] = status.seeding_time;
data[KEY_PROP_CONNECT_COUNT] = status.num_connections;
data[KEY_PROP_CONNECT_COUNT_LIMIT] = status.connections_limit;
const qreal ratio = QBtSession::instance()->getRealRatio(status);
data[KEY_PROP_RATIO] = ratio > 100. ? QString::fromUtf8("") : misc::accurateDoubleToString(ratio, 1, false);
data[KEY_PROP_RATIO] = ratio > 100. ? -1 : ratio;
} catch(const std::exception& e) {
qWarning() << Q_FUNC_INFO << "Invalid torrent: " << misc::toQStringU(e.what());
return QByteArray();
@ -350,7 +360,7 @@ QByteArray btjson::getFilesForTorrent(const QString& hash) @@ -350,7 +360,7 @@ QByteArray btjson::getFilesForTorrent(const QString& hash)
fileName.chop(4);
file_dict[KEY_FILE_NAME] = fsutils::toNativePath(fileName);
const size_type size = h.filesize_at(i);
file_dict[KEY_FILE_SIZE] = misc::friendlyUnit(size, false, true);
file_dict[KEY_FILE_SIZE] = static_cast<qlonglong>(size);
file_dict[KEY_FILE_PROGRESS] = (size > 0) ? (fp[i] / (double) size) : 1.;
file_dict[KEY_FILE_PRIORITY] = priorities[i];
if (i == 0)
@ -371,14 +381,18 @@ QByteArray btjson::getFilesForTorrent(const QString& hash) @@ -371,14 +381,18 @@ QByteArray btjson::getFilesForTorrent(const QString& hash)
*
* The return value is a JSON-formatted dictionary.
* The dictionary keys are:
* - "dl_info": Global download info
* - "up_info": Global upload info
* - "dl_info_speed": Global download rate
* - "dl_info_data": Data downloaded this session
* - "up_info_speed": Global upload rate
* - "up_info_data": Data uploaded this session
*/
QByteArray btjson::getTransferInfo()
{
CACHED_VARIABLE(QVariantMap, info, CACHE_DURATION_MS);
session_status sessionStatus = QBtSession::instance()->getSessionStatus();
info[KEY_TRANSFER_DLSPEED] = tr("D: %1/s - T: %2", "Download speed: x KiB/s - Transferred: x MiB").arg(misc::friendlyUnit(sessionStatus.payload_download_rate, true, true)).arg(misc::friendlyUnit(sessionStatus.total_payload_download, false, true));
info[KEY_TRANSFER_UPSPEED] = tr("U: %1/s - T: %2", "Upload speed: x KiB/s - Transferred: x MiB").arg(misc::friendlyUnit(sessionStatus.payload_upload_rate, true, true)).arg(misc::friendlyUnit(sessionStatus.total_payload_upload, false, true));
info[KEY_TRANSFER_DLSPEED] = sessionStatus.payload_download_rate;
info[KEY_TRANSFER_DLDATA] = static_cast<qlonglong>(sessionStatus.total_payload_download);
info[KEY_TRANSFER_UPSPEED] = sessionStatus.payload_upload_rate;
info[KEY_TRANSFER_UPDATA] = static_cast<qlonglong>(sessionStatus.total_payload_upload);
return json::toJson(info);
}

1
src/webui/webui.qrc

@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
<file>www/public/scripts/download.js</file>
<file>www/public/scripts/dynamicTable.js</file>
<file>www/public/scripts/excanvas-compressed.js</file>
<file>www/public/scripts/misc.js</file>
<file>www/public/scripts/mocha.js</file>
<file>www/public/scripts/mocha-init.js</file>
<file>www/public/scripts/mocha-yc.js</file>

1
src/webui/www/private/index.html

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
<![endif]-->
<script type="text/javascript" src="scripts/mocha-yc.js"></script>
<script type="text/javascript" src="scripts/mocha-init.js"></script>
<script type="text/javascript" src="scripts/misc.js"></script>
<script type="text/javascript" src="scripts/progressbar.js"></script>
<script type="text/javascript" src="scripts/dynamicTable.js" charset="utf-8"></script>
<script type="text/javascript" src="scripts/client.js" charset="utf-8"></script>

2
src/webui/www/public/prop-files.html

@ -303,7 +303,7 @@ var createPriorityCombo = function(id, selected_prio) { @@ -303,7 +303,7 @@ var createPriorityCombo = function(id, selected_prio) {
row.length = 4;
row[0] = file.priority;
row[1] = file.name;
row[2] = file.size;
row[2] = friendlyUnit(file.size, false);
row[3] = (file.progress*100).round(1);
if(row[3] == 100.0 && file.progress < 1.0)
row[3] = 99.9

33
src/webui/www/public/prop-general.html

@ -80,19 +80,34 @@ dynamic information: total_downloaded, total_uploaded, total_wasted, up_limit, d @@ -80,19 +80,34 @@ dynamic information: total_downloaded, total_uploaded, total_wasted, up_limit, d
onSuccess: function(data) {
$('error_div').set('html', '');
if(data){
var temp;
// Update Torrent data
$('save_path').set('html', data.save_path);
$('creation_date').set('html', data.creation_date);
$('piece_size').set('html', data.piece_size);
temp = data.creation_date;
var timestamp = "_(Unknown)";
if (temp != -1)
timestamp = new Date(data.creation_date*1000).toISOString();
$('creation_date').set('html', timestamp);
$('piece_size').set('html', friendlyUnit(data.piece_size));
$('comment').set('html', data.comment);
$('total_uploaded').set('html', data.total_uploaded);
$('total_downloaded').set('html', data.total_downloaded);
$('total_uploaded').set('html', friendlyUnit(data.total_uploaded) +
" (" + friendlyUnit(data.total_uploaded_session) +
" (" + "_(this session)" + ")");
$('total_downloaded').set('html', friendlyUnit(data.total_downloaded) +
" (" + friendlyUnit(data.total_downloaded_session) +
" (" + "_(this session)" + ")");
$('total_wasted').set('html', data.total_wasted);
$('up_limit').set('html', data.up_limit);
$('dl_limit').set('html', data.dl_limit);
$('time_elapsed').set('html', data.time_elapsed);
$('nb_connections').set('html', data.nb_connections);
$('share_ratio').set('html', data.share_ratio);
temp = data.up_limit;
$('up_limit').set('html', temp == -1 ? "∞" : temp);
temp = data.dl_limit;
$('dl_limit').set('html', temp == -1 ? "∞" : temp);
temp = friendlyDuration(status.active_time);
if (status.is_seed)
temp += " (" + "_(Seeded for %1)".replace("%1", status.seeding_time) + ")";
$('time_elapsed').set('html', temp);
temp = data.nb_connections + " (" + "_(%1 max)".replace("%1", status.nb_connections_limit) + ")";
$('nb_connections').set('html', temp);
$('share_ratio').set('html', data.share_ratio.toFixed(2));
} else {
clearData();
}

31
src/webui/www/public/scripts/client.js

@ -108,8 +108,10 @@ window.addEvent('load', function(){ @@ -108,8 +108,10 @@ window.addEvent('load', function(){
},
onSuccess: function(info) {
if(info) {
$("DlInfos").set('html', info.dl_info);
$("UpInfos").set('html', info.up_info);
$("DlInfos").set('html', "_(D: %1 - T: %2)".replace("%1", friendlyUnit(info.dl_info_speed, true))
.replace("%2", friendlyUnit(info.dl_info_data, false)));
$("UpInfos").set('html', "_(U: %1 - T: %2)".replace("%1", friendlyUnit(info.up_info_speed, true))
.replace("%2", friendlyUnit(info.up_info_data, false)));
waitingTrInfo=false;
loadTransferInfo.delay(3000);
}
@ -146,18 +148,25 @@ window.addEvent('load', function(){ @@ -146,18 +148,25 @@ window.addEvent('load', function(){
row.length = 10;
row[0] = stateToImg(event.state);
row[1] = event.name;
row[2] = event.priority
row[3] = event.size;
row[2] = event.priority > -1 ? event.priority : null;
row[3] = friendlyUnit(event.size, false);
row[4] = (event.progress*100).round(1);
if(row[4] == 100.0 && event.progress != 1.0)
row[4] = 99.9;
row[5] = event.num_seeds;
row[6] = event.num_leechs;
row[7] = event.dlspeed;
row[8] = event.upspeed;
row[9] = event.eta;
row[10] = event.ratio;
if(row[2] != "*")
row[5] = event.num_seeds;
if (event.num_complete != -1)
row[5] += " (" + event.num_complete + ")";
row[6] = event.num_leechs;
if (event.num_incomplete != -1)
row[6] += " (" + event.num_incomplete + ")";
row[7] = friendlyUnit(event.dlspeed, true);
row[8] = friendlyUnit(event.upspeed, true);
row[9] = friendlyDuration(event.eta);
if(event.ratio == -1)
row[10] = "∞";
else
row[10] = (Math.floor(100 * event.ratio) / 100).toFixed(2); //Don't round up
if(row[2] != null)
queueing_enabled = true;
if(!torrent_hashes.contains(event.hash)) {
// New unfinished torrent

78
src/webui/www/public/scripts/misc.js

@ -0,0 +1,78 @@ @@ -0,0 +1,78 @@
/*
* JS counterpart of the function in src/misc.cpp
*/
function friendlyUnit(value, isSpeed) {
units = [
"_(B)",
"_(KiB)",
"_(MiB)",
"_(GiB)",
"_(TiB)",
];
if (value < 0)
return "_(Unknown)";
var i = 0;
while (value >= 1024. && i++ < 6)
value /= 1024.;
var ret;
if (i == 0)
ret = value.toFixed(2) + " " + units[0];
else
ret = value.toFixed(2) + " " + units[i];
if (isSpeed)
ret += "_(/s)";
return ret;
}
/*
* JS counterpart of the function in src/misc.cpp
*/
function friendlyDuration(seconds) {
var MAX_ETA = 8640000;
if (seconds < 0 || seconds >= MAX_ETA)
return "∞";
if (seconds == 0)
return "0";
if (seconds < 60)
return "< " + "_(%1m)".replace("%1", "1"); //translation of "< 1m" not working
var minutes = seconds / 60;
if (minutes < 60)
return "_(%1m)".replace("%1", parseInt(minutes));
var hours = minutes / 60;
minutes = minutes - hours*60;
if (hours < 24)
return "_(%1h %2m)".replace("%1", parseInt(hours)).replace("%2", parseInt(minutes))
var days = hours / 24;
hours = hours - days * 24;
if (days < 100)
return "_(%1d %2h)".replace("%1", parseInt(days)).replace("%2", parseInt(hours))
return "∞";
}
/*
* From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
*/
if (!Date.prototype.toISOString) {
(function() {
function pad(number) {
if (number < 10) {
return '0' + number;
}
return number;
}
Date.prototype.toISOString = function() {
return this.getUTCFullYear() +
'-' + pad(this.getUTCMonth() + 1) +
'-' + pad(this.getUTCDate()) +
'T' + pad(this.getUTCHours()) +
':' + pad(this.getUTCMinutes()) +
':' + pad(this.getUTCSeconds()) +
'.' + (this.getUTCMilliseconds() / 1000).toFixed(3).slice(2, 5) +
'Z';
};
}());
}
Loading…
Cancel
Save