transmission/web/javascript/torrent-row.js

417 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 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());
};
TorrentRendererHelper.formatETA = function (t) {
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 = '';
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();
}
};