mirror of
https://github.com/transmission/transmission
synced 2024-12-23 16:24:02 +00:00
406 lines
10 KiB
JavaScript
406 lines
10 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,
|
|
s = t.getStatus(),
|
|
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,
|
|
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());
|
|
};
|
|
|
|
/****
|
|
*****
|
|
*****
|
|
****/
|
|
|
|
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 percent = 100 * t.getMetadataPercentComplete();
|
|
return [ "Magnetized transfer - retrieving metadata (",
|
|
Transmission.fmt.percentString(percent),
|
|
"%)" ].join('');
|
|
}
|
|
|
|
var c,
|
|
sizeWhenDone = t.getSizeWhenDone(),
|
|
totalSize = t.getTotalSize(),
|
|
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,
|
|
have_up = t.getUploadSpeed() > 0;
|
|
if (!have_up && !have_dn)
|
|
return 'Idle';
|
|
var s = '';
|
|
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();
|
|
}
|
|
};
|