transmission/web/javascript/torrent-row.js

417 lines
13 KiB
JavaScript
Raw Normal View History

/**
* Copyright © Mnemosyne LLC
*
* This file is licensed under the GPLv2.
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
function TorrentRendererHelper() {}
TorrentRendererHelper.getProgressInfo = function (controller, t) {
var pct, extra;
var s = t.getStatus();
var seed_ratio_limit = t.seedRatioLimit(controller);
if (t.needsMetaData()) {
pct = t.getMetadataPercentComplete() * 100;
} else if (!t.isDone()) {
pct = Math.round(t.getPercentDone() * 100);
} else if (seed_ratio_limit > 0 && t.isSeeding()) { // don't split up the bar if paused or queued
pct = Math.round(t.getUploadRatio() * 100 / seed_ratio_limit);
} else {
pct = 100;
};
if (s === Torrent._StatusStopped) {
extra = 'paused';
} else if (s === Torrent._StatusDownloadWait) {
extra = 'leeching queued';
} else if (t.needsMetaData()) {
extra = 'magnet';
} else if (s === Torrent._StatusDownload) {
extra = 'leeching';
} else if (s === Torrent._StatusSeedWait) {
extra = 'seeding queued';
} else if (s === Torrent._StatusSeed) {
extra = 'seeding';
} else {
extra = '';
};
return {
percent: pct,
complete: ['torrent_progress_bar', 'complete', extra].join(' '),
incomplete: ['torrent_progress_bar', 'incomplete', extra].join(' ')
};
};
TorrentRendererHelper.createProgressbar = function (classes) {
var complete, incomplete, progressbar;
complete = document.createElement('div');
complete.className = 'torrent_progress_bar complete';
incomplete = document.createElement('div');
incomplete.className = 'torrent_progress_bar incomplete';
progressbar = document.createElement('div');
progressbar.className = 'torrent_progress_bar_container ' + classes;
progressbar.appendChild(complete);
progressbar.appendChild(incomplete);
return {
'element': progressbar,
'complete': complete,
'incomplete': incomplete
};
};
TorrentRendererHelper.renderProgressbar = function (controller, t, progressbar) {
var e, style, width, display;
var info = TorrentRendererHelper.getProgressInfo(controller, t);
// update the complete progressbar
e = progressbar.complete;
style = e.style;
width = '' + info.percent + '%';
display = info.percent > 0 ? 'block' : 'none';
if (style.width !== width || style.display !== display) {
$(e).css({
width: '' + info.percent + '%',
display: display
});
};
if (e.className !== info.complete) {
e.className = info.complete;
};
// update the incomplete progressbar
e = progressbar.incomplete;
display = (info.percent < 100) ? 'block' : 'none';
if (e.style.display !== display) {
e.style.display = display;
};
if (e.className !== info.incomplete) {
e.className = info.incomplete;
};
};
TorrentRendererHelper.formatUL = function (t) {
return '▲' + Transmission.fmt.speedBps(t.getUploadSpeed());
};
TorrentRendererHelper.formatDL = function (t) {
return '▼' + Transmission.fmt.speedBps(t.getDownloadSpeed());
};
2019-02-17 14:51:13 +00:00
TorrentRendererHelper.formatETA = function (t) {
2017-01-13 16:48:14 +00:00
var eta = t.getETA();
if (eta < 0 || eta >= (999 * 60 * 60)) {
return "";
};
return "ETA: " + Transmission.fmt.timeInterval(eta);
};
/****
*****
*****
****/
function TorrentRendererFull() {};
TorrentRendererFull.prototype = {
createRow: function () {
var root, name, peers, progressbar, details, image, button;
root = document.createElement('li');
root.className = 'torrent';
name = document.createElement('div');
name.className = 'torrent_name';
peers = document.createElement('div');
peers.className = 'torrent_peer_details';
progressbar = TorrentRendererHelper.createProgressbar('full');
details = document.createElement('div');
details.className = 'torrent_progress_details';
image = document.createElement('div');
button = document.createElement('a');
button.appendChild(image);
root.appendChild(name);
root.appendChild(peers);
root.appendChild(button);
root.appendChild(progressbar.element);
root.appendChild(details);
root._name_container = name;
root._peer_details_container = peers;
root._progress_details_container = details;
root._progressbar = progressbar;
root._pause_resume_button_image = image;
root._toggle_running_button = button;
return root;
},
getPeerDetails: function (t) {
var err,
peer_count,
webseed_count,
fmt = Transmission.fmt;
if ((err = t.getErrorMessage())) {
return err;
};
if (t.isDownloading()) {
peer_count = t.getPeersConnected();
webseed_count = t.getWebseedsSendingToUs();
if (webseed_count && peer_count) {
// Downloading from 2 of 3 peer(s) and 2 webseed(s)
return ['Downloading from',
t.getPeersSendingToUs(),
'of',
fmt.countString('peer', 'peers', peer_count),
'and',
fmt.countString('web seed', 'web seeds', webseed_count),
'',
TorrentRendererHelper.formatDL(t),
TorrentRendererHelper.formatUL(t)
].join(' ');
} else if (webseed_count) {
// Downloading from 2 webseed(s)
return ['Downloading from',
fmt.countString('web seed', 'web seeds', webseed_count),
'',
TorrentRendererHelper.formatDL(t),
TorrentRendererHelper.formatUL(t)
].join(' ');
} else {
// Downloading from 2 of 3 peer(s)
return ['Downloading from',
t.getPeersSendingToUs(),
'of',
fmt.countString('peer', 'peers', peer_count),
'',
TorrentRendererHelper.formatDL(t),
TorrentRendererHelper.formatUL(t)
].join(' ');
};
};
if (t.isSeeding()) {
return ['Seeding to', t.getPeersGettingFromUs(), 'of', fmt.countString('peer', 'peers', t.getPeersConnected()), '-', TorrentRendererHelper.formatUL(t)].join(' ');
};
if (t.isChecking()) {
return ['Verifying local data (', Transmission.fmt.percentString(100.0 * t.getRecheckProgress()), '% tested)'].join('');
}
return t.getStateString();
},
getProgressDetails: function (controller, t) {
if (t.needsMetaData()) {
var MetaDataStatus = "retrieving";
if (t.isStopped()) {
MetaDataStatus = "needs";
};
var percent = 100 * t.getMetadataPercentComplete();
return ["Magnetized transfer - " + MetaDataStatus + " metadata (",
Transmission.fmt.percentString(percent),
"%)"
].join('');
}
var c;
var sizeWhenDone = t.getSizeWhenDone();
var totalSize = t.getTotalSize();
var is_done = t.isDone() || t.isSeeding();
if (is_done) {
if (totalSize === sizeWhenDone) {
// seed: '698.05 MiB'
c = [Transmission.fmt.size(totalSize)];
} else { // partial seed: '127.21 MiB of 698.05 MiB (18.2%)'
c = [Transmission.fmt.size(sizeWhenDone), ' of ', Transmission.fmt.size(t.getTotalSize()), ' (', t.getPercentDoneStr(), '%)'];
};
// append UL stats: ', uploaded 8.59 GiB (Ratio: 12.3)'
c.push(', uploaded ',
Transmission.fmt.size(t.getUploadedEver()),
' (Ratio ',
Transmission.fmt.ratioString(t.getUploadRatio()),
')');
} else { // not done yet
c = [Transmission.fmt.size(sizeWhenDone - t.getLeftUntilDone()),
' of ', Transmission.fmt.size(sizeWhenDone),
' (', t.getPercentDoneStr(), '%)'
];
};
// maybe append eta
if (!t.isStopped() && (!is_done || t.seedRatioLimit(controller) > 0)) {
c.push(' - ');
var eta = t.getETA();
if (eta < 0 || eta >= (999 * 60 * 60) /* arbitrary */ ) {
c.push('remaining time unknown');
} else {
c.push(Transmission.fmt.timeInterval(t.getETA()), ' remaining');
};
};
return c.join('');
},
render: function (controller, t, root) {
// name
setTextContent(root._name_container, t.getName());
// progressbar
TorrentRendererHelper.renderProgressbar(controller, t, root._progressbar);
// peer details
var has_error = t.getError() !== Torrent._ErrNone;
var e = root._peer_details_container;
$(e).toggleClass('error', has_error);
setTextContent(e, this.getPeerDetails(t));
// progress details
e = root._progress_details_container;
setTextContent(e, this.getProgressDetails(controller, t));
// pause/resume button
var is_stopped = t.isStopped();
e = root._pause_resume_button_image;
e.alt = is_stopped ? 'Resume' : 'Pause';
e.className = is_stopped ? 'torrent_resume' : 'torrent_pause';
}
};
/****
*****
*****
****/
function TorrentRendererCompact() {};
TorrentRendererCompact.prototype = {
createRow: function () {
var progressbar, details, name, root;
progressbar = TorrentRendererHelper.createProgressbar('compact');
details = document.createElement('div');
details.className = 'torrent_peer_details compact';
name = document.createElement('div');
name.className = 'torrent_name compact';
root = document.createElement('li');
root.appendChild(progressbar.element);
root.appendChild(details);
root.appendChild(name);
root.className = 'torrent compact';
root._progressbar = progressbar;
root._details_container = details;
root._name_container = name;
return root;
},
getPeerDetails: function (t) {
var c;
if ((c = t.getErrorMessage())) {
return c;
};
if (t.isDownloading()) {
var have_dn = t.getDownloadSpeed() > 0;
var have_up = t.getUploadSpeed() > 0;
if (!have_up && !have_dn) {
return 'Idle';
};
var s = '';
2017-01-13 16:48:14 +00:00
if (!isMobileDevice) {
s = TorrentRendererHelper.formatETA(t) + ' ';
};
if (have_dn) {
s += TorrentRendererHelper.formatDL(t);
};
if (have_dn && have_up) {
s += ' ';
};
if (have_up) {
s += TorrentRendererHelper.formatUL(t);
};
return s;
};
if (t.isSeeding()) {
return ['Ratio: ', Transmission.fmt.ratioString(t.getUploadRatio()), ', ', TorrentRendererHelper.formatUL(t)].join('');
};
return t.getStateString();
},
render: function (controller, t, root) {
// name
var is_stopped = t.isStopped();
var e = root._name_container;
$(e).toggleClass('paused', is_stopped);
setTextContent(e, t.getName());
// peer details
var has_error = t.getError() !== Torrent._ErrNone;
e = root._details_container;
$(e).toggleClass('error', has_error);
setTextContent(e, this.getPeerDetails(t));
// progressbar
TorrentRendererHelper.renderProgressbar(controller, t, root._progressbar);
}
};
/****
*****
*****
****/
function TorrentRow(view, controller, torrent) {
this.initialize(view, controller, torrent);
};
TorrentRow.prototype = {
initialize: function (view, controller, torrent) {
var row = this;
this._view = view;
this._torrent = torrent;
this._element = view.createRow();
this.render(controller);
$(this._torrent).bind('dataChanged.torrentRowListener', function () {
row.render(controller);
});
},
getElement: function () {
return this._element;
},
render: function (controller) {
var tor = this.getTorrent();
if (tor) {
this._view.render(controller, tor, this.getElement());
};
},
isSelected: function () {
return this.getElement().className.indexOf('selected') !== -1;
},
getTorrent: function () {
return this._torrent;
},
getTorrentId: function () {
return this.getTorrent().getId();
}
};