mirror of
https://github.com/transmission/transmission
synced 2024-12-30 19:46:56 +00:00
660b44da70
The current icons are very hard to read at the current font size and it's not immediately visible which icon i which. Additionally, spaces after icons are removed because upload icon is equally positioned between DL/UL speeds (like so `↓ 273 kB/s **↑** 0 kB/s`) which requires reading the whole line to make sense of which number the arrow applies to. To further separate one type of information from another the hyphen is replaced by the slightly wider en dash. Old vs New: Downloading from 7 of 19 peers - ↓ 273 kB/s ↑ 167 kB/s Downloading from 7 of 19 peers – ▼273 kB/s ▲167 kB/s
416 lines
13 KiB
JavaScript
416 lines
13 KiB
JavaScript
/**
|
||
* 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();
|
||
}
|
||
};
|