mirror of
https://github.com/transmission/transmission.git
synced 2025-12-20 18:38:42 +00:00
(trunk web) significant shrinkage of our memory + network footprint by only loading torrent's fields when they're needed.
This commit is contained in:
@@ -90,7 +90,7 @@ FileRow.prototype =
|
|||||||
{
|
{
|
||||||
var i = this.getIndex();
|
var i = this.getIndex();
|
||||||
var t = this.getTorrent();
|
var t = this.getTorrent();
|
||||||
this.readAttributes(t._files[i]);
|
this.readAttributes(t.getFile(i));
|
||||||
this.refreshHTML();
|
this.refreshHTML();
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -98,13 +98,13 @@ FileRow.prototype =
|
|||||||
return this._done >= this._size;
|
return this._done >= this._size;
|
||||||
},
|
},
|
||||||
isEditable: function () {
|
isEditable: function () {
|
||||||
return (this.getTorrent()._files.length>1) && !this.isDone();
|
return (this.getTorrent().getFileCount()>1) && !this.isDone();
|
||||||
},
|
},
|
||||||
|
|
||||||
createRow: function(torrent, i)
|
createRow: function(torrent, i)
|
||||||
{
|
{
|
||||||
var me = this;
|
var me = this;
|
||||||
var file = torrent._files[i];
|
var file = torrent.getFile(i);
|
||||||
var name = file.name.substring (file.name.lastIndexOf('/')+1);
|
var name = file.name.substring (file.name.lastIndexOf('/')+1);
|
||||||
|
|
||||||
var root = document.createElement('li');
|
var root = document.createElement('li');
|
||||||
|
|||||||
@@ -45,25 +45,79 @@ Torrent._TrackerQueued = 2;
|
|||||||
Torrent._TrackerActive = 3;
|
Torrent._TrackerActive = 3;
|
||||||
|
|
||||||
|
|
||||||
// fields whose values never change and are always known
|
Torrent.Fields = { };
|
||||||
Torrent._StaticFields = [
|
|
||||||
'hashString', 'id' ];
|
|
||||||
|
|
||||||
// fields whose values never change and are known upon constructon OR
|
// commonly used fields which only need to be loaded once,
|
||||||
// when a magnet torrent finishes downloading its metadata
|
// either on startup or when a magnet finishes downloading its metadata
|
||||||
Torrent._MetaDataFields = [
|
// finishes downloading its metadata
|
||||||
'addedDate', 'comment', 'creator', 'dateCreated',
|
Torrent.Fields.Metadata = [
|
||||||
'isPrivate', 'name', 'totalSize', 'pieceCount', 'pieceSize' ];
|
'addedDate',
|
||||||
|
'name',
|
||||||
|
'totalSize'
|
||||||
|
];
|
||||||
|
|
||||||
// torrent fields whose values change all the time
|
// commonly used fields which need to be periodically refreshed
|
||||||
Torrent._DynamicFields = [
|
Torrent.Fields.Stats = [
|
||||||
'desiredAvailable', 'downloadDir', 'downloadedEver', 'error',
|
'error',
|
||||||
'errorString', 'eta', 'haveUnchecked', 'haveValid', 'isFinished',
|
'errorString',
|
||||||
'leftUntilDone', 'metadataPercentComplete', 'peers', 'peersConnected',
|
'eta',
|
||||||
'peersGettingFromUs', 'peersSendingToUs', 'queuePosition',
|
'isFinished',
|
||||||
'rateDownload', 'rateUpload', 'recheckProgress', 'seedRatioLimit',
|
'isStalled',
|
||||||
'seedRatioMode', 'sizeWhenDone', 'status', 'trackerStats',
|
'leftUntilDone',
|
||||||
'uploadedEver', 'uploadRatio', 'webseedsSendingToUs' ];
|
'metadataPercentComplete',
|
||||||
|
'peersConnected',
|
||||||
|
'peersGettingFromUs',
|
||||||
|
'peersSendingToUs',
|
||||||
|
'percentDone',
|
||||||
|
'queuePosition',
|
||||||
|
'rateDownload',
|
||||||
|
'rateUpload',
|
||||||
|
'recheckProgress',
|
||||||
|
'seedRatioMode',
|
||||||
|
'sizeWhenDone',
|
||||||
|
'status',
|
||||||
|
'trackers',
|
||||||
|
'uploadedEver',
|
||||||
|
'uploadRatio'
|
||||||
|
];
|
||||||
|
|
||||||
|
// fields used by the inspector which only need to be loaded once
|
||||||
|
Torrent.Fields.InfoExtra = [
|
||||||
|
'comment',
|
||||||
|
'creator',
|
||||||
|
'dateCreated',
|
||||||
|
'files',
|
||||||
|
'hashString',
|
||||||
|
'isPrivate',
|
||||||
|
'pieceCount',
|
||||||
|
'pieceSize'
|
||||||
|
];
|
||||||
|
|
||||||
|
// fields used in the inspector which need to be periodically refreshed
|
||||||
|
Torrent.Fields.StatsExtra = [
|
||||||
|
'activityDate',
|
||||||
|
'desiredAvailable',
|
||||||
|
'downloadDir',
|
||||||
|
'downloadLimit',
|
||||||
|
'downloadLimited',
|
||||||
|
'downloadedEver',
|
||||||
|
'fileStats',
|
||||||
|
'haveUnchecked',
|
||||||
|
'haveValid',
|
||||||
|
'honorsSessionLimits',
|
||||||
|
'manualAnnounceTime',
|
||||||
|
'peer-limit',
|
||||||
|
'peers',
|
||||||
|
'seedIdleLimit',
|
||||||
|
'seedIdleMode',
|
||||||
|
'seedRatioLimit',
|
||||||
|
'startDate',
|
||||||
|
'torrentFile',
|
||||||
|
'trackerStats',
|
||||||
|
'uploadLimited',
|
||||||
|
'uploadLimit',
|
||||||
|
'webseedsSendingToUs'
|
||||||
|
];
|
||||||
|
|
||||||
/***
|
/***
|
||||||
****
|
****
|
||||||
@@ -76,129 +130,76 @@ Torrent.prototype =
|
|||||||
initialize: function(data)
|
initialize: function(data)
|
||||||
{
|
{
|
||||||
this.fields = {};
|
this.fields = {};
|
||||||
this._files = [];
|
this.refresh (data);
|
||||||
|
|
||||||
// these fields are set in the ctor and never change
|
|
||||||
for (var i=0, key; key=Torrent._StaticFields[i]; ++i) {
|
|
||||||
if (key in data) {
|
|
||||||
this.fields[key] = data[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.initMetaData(data);
|
|
||||||
this._trackerStats = this.buildTrackerStats(data.trackerStats);
|
|
||||||
this.refresh(data);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
buildTrackerStats: function(trackerStats) {
|
setField: function(o, name, value)
|
||||||
var announce = [];
|
{
|
||||||
var result = [];
|
var changed = !(name in o) || (o[name] !== value);
|
||||||
for (var i=0, tracker; tracker=trackerStats[i]; ++i) {
|
if (changed)
|
||||||
var tier = result[tracker.tier] || [];
|
o[name] = value;
|
||||||
tier.push(tracker);
|
|
||||||
result[tracker.tier] = tier;
|
|
||||||
announce.push(tracker.announce);
|
|
||||||
}
|
|
||||||
this.fields.collatedTrackers = announce.join('\t');
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
|
|
||||||
initMetaData: function(data) {
|
|
||||||
|
|
||||||
var f = this.fields;
|
|
||||||
var changed = false;
|
|
||||||
|
|
||||||
// populate the metadata fields
|
|
||||||
for (var i=0, key; key=Torrent._MetaDataFields[i]; ++i) {
|
|
||||||
if (key in data) {
|
|
||||||
if (f[key] !== data[key]) {
|
|
||||||
f[key] = data[key];
|
|
||||||
if (key === 'name')
|
|
||||||
f.collatedName = data.name.toLowerCase();
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// populate the files array
|
|
||||||
if (data.files) {
|
|
||||||
for (var i=0, row; row=data.files[i]; ++i) {
|
|
||||||
this._files[i] = {
|
|
||||||
'index': i,
|
|
||||||
'length': row.length,
|
|
||||||
'name': row.name
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
},
|
},
|
||||||
|
|
||||||
refreshMetaData: function(data)
|
// fields.files is an array of unions of RPC's "files" and "fileStats" objects.
|
||||||
|
updateFiles: function(files) {
|
||||||
|
var changed = false;
|
||||||
|
var myfiles = this.fields.files || [];
|
||||||
|
var keys = [ 'length', 'name', 'bytesCompleted', 'wanted', 'priority' ];
|
||||||
|
for (var i=0, f; f=files[i]; ++i) {
|
||||||
|
var myfile = myfiles[i] || {};
|
||||||
|
for (var j=0, key; key=keys[j]; ++j)
|
||||||
|
if(key in f)
|
||||||
|
changed |= this.setField(myfile,key,f[key]);
|
||||||
|
myfiles[i] = myfile;
|
||||||
|
}
|
||||||
|
this.fields.files = myfiles;
|
||||||
|
return changed;
|
||||||
|
},
|
||||||
|
|
||||||
|
collateTrackers: function(trackers) {
|
||||||
|
announces = [];
|
||||||
|
for (var i=0, t; t=trackers[i]; ++i)
|
||||||
|
announces.push(t.announce.toLowerCase());
|
||||||
|
return announces.join('\t');
|
||||||
|
},
|
||||||
|
|
||||||
|
isField: function(name) {
|
||||||
|
return ( name === 'id' )
|
||||||
|
|| ( Torrent.Fields.Stats.indexOf(name) !== -1 )
|
||||||
|
|| ( Torrent.Fields.StatsExtra.indexOf(name) !== -1 )
|
||||||
|
|| ( Torrent.Fields.InfoExtra.indexOf(name) !== -1 )
|
||||||
|
|| ( Torrent.Fields.Metadata.indexOf(name) !== -1 );
|
||||||
|
},
|
||||||
|
|
||||||
|
refreshFields: function(data)
|
||||||
{
|
{
|
||||||
var changed = this.initMetaData(data);
|
var changed = false;
|
||||||
if (changed)
|
|
||||||
this.fireDataChanged();
|
for (var key in data) {
|
||||||
|
if (this.isField(key)) switch (key) {
|
||||||
|
case 'files':
|
||||||
|
case 'fileStats': // merge files and fileStats together
|
||||||
|
changed |= this.updateFiles(data[key]);
|
||||||
|
break;
|
||||||
|
case 'trackerStats': // 'trackerStats' is a superset of 'trackers'...
|
||||||
|
changed |= this.setField(this.fields,'trackers',data[key]);
|
||||||
|
case 'trackers': // ...so only save 'trackers' if we don't have it already
|
||||||
|
if (!(key in this.fields))
|
||||||
|
changed |= this.setField(this.fields,key,data[key]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
changed |= this.setField(this.fields,key,data[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: function(data)
|
refresh: function(data)
|
||||||
{
|
{
|
||||||
var changed = false;
|
if (this.refreshFields(data))
|
||||||
|
$(this).trigger('dataChanged');
|
||||||
// FIXME: unnecessary coupling... this should be handled by transmission.js
|
|
||||||
if (this.needsMetaData() && (data.metadataPercentComplete >= 1))
|
|
||||||
changed |= transmission.refreshMetaData([ this.getId() ]);
|
|
||||||
|
|
||||||
var f = this.fields;
|
|
||||||
|
|
||||||
// refresh the dynamic fields
|
|
||||||
for (var i=0, key; key=Torrent._DynamicFields[i]; ++i) {
|
|
||||||
if (key in data) {
|
|
||||||
if (f[key] !== data[key]) {
|
|
||||||
f[key] = data[key];
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._trackerStats = this.buildTrackerStats(data.trackerStats);
|
|
||||||
|
|
||||||
if (data.fileStats)
|
|
||||||
changed |= this.refreshFiles(data);
|
|
||||||
|
|
||||||
if (changed)
|
|
||||||
this.fireDataChanged();
|
|
||||||
},
|
|
||||||
|
|
||||||
refreshFiles: function(data) {
|
|
||||||
var changed = false;
|
|
||||||
for (var i=0; i<data.fileStats.length; ++i) {
|
|
||||||
var src = data.fileStats[i];
|
|
||||||
var tgt = this._files[i];
|
|
||||||
if (!tgt) {
|
|
||||||
changed = true;
|
|
||||||
tgt = this._files[i] = { };
|
|
||||||
}
|
|
||||||
if (tgt.wanted !== src.wanted) {
|
|
||||||
tgt.wanted = src.wanted;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
if (tgt.priority !== src.priority) {
|
|
||||||
tgt.priority = src.priority;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
if (tgt.bytesCompleted !== src.bytesCompleted) {
|
|
||||||
tgt.bytesCompleted = src.bytesCompleted;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return changed;
|
|
||||||
},
|
|
||||||
|
|
||||||
fireDataChanged: function()
|
|
||||||
{
|
|
||||||
$(this).trigger('dataChanged');
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/****
|
/****
|
||||||
@@ -219,6 +220,8 @@ Torrent.prototype =
|
|||||||
getError: function() { return this.fields.error; },
|
getError: function() { return this.fields.error; },
|
||||||
getErrorString: function() { return this.fields.errorString; },
|
getErrorString: function() { return this.fields.errorString; },
|
||||||
getETA: function() { return this.fields.eta; },
|
getETA: function() { return this.fields.eta; },
|
||||||
|
getFile: function(i) { return this.fields.files[i]; },
|
||||||
|
getFileCount: function() { return this.fields.files ? this.fields.files.length : 0; },
|
||||||
getHashString: function() { return this.fields.hashString; },
|
getHashString: function() { return this.fields.hashString; },
|
||||||
getHaveValid: function() { return this.fields.haveValid; },
|
getHaveValid: function() { return this.fields.haveValid; },
|
||||||
getHave: function() { return this.getHaveValid() + this.fields.haveUnchecked; },
|
getHave: function() { return this.getHaveValid() + this.fields.haveUnchecked; },
|
||||||
@@ -231,7 +234,6 @@ Torrent.prototype =
|
|||||||
getPeersGettingFromUs: function() { return this.fields.peersGettingFromUs; },
|
getPeersGettingFromUs: function() { return this.fields.peersGettingFromUs; },
|
||||||
getPeersSendingToUs: function() { return this.fields.peersSendingToUs; },
|
getPeersSendingToUs: function() { return this.fields.peersSendingToUs; },
|
||||||
getPieceCount: function() { return this.fields.pieceCount; },
|
getPieceCount: function() { return this.fields.pieceCount; },
|
||||||
getPieceCount: function() { return this.fields.pieceCount; },
|
|
||||||
getPieceSize: function() { return this.fields.pieceSize; },
|
getPieceSize: function() { return this.fields.pieceSize; },
|
||||||
getPrivateFlag: function() { return this.fields.isPrivate; },
|
getPrivateFlag: function() { return this.fields.isPrivate; },
|
||||||
getQueuePosition: function() { return this.fields.queuePosition; },
|
getQueuePosition: function() { return this.fields.queuePosition; },
|
||||||
@@ -241,6 +243,7 @@ Torrent.prototype =
|
|||||||
getSizeWhenDone: function() { return this.fields.sizeWhenDone; },
|
getSizeWhenDone: function() { return this.fields.sizeWhenDone; },
|
||||||
getStatus: function() { return this.fields.status; },
|
getStatus: function() { return this.fields.status; },
|
||||||
getTotalSize: function() { return this.fields.totalSize; },
|
getTotalSize: function() { return this.fields.totalSize; },
|
||||||
|
getTrackers: function() { return this.fields.trackers; },
|
||||||
getUploadSpeed: function() { return this.fields.rateUpload; },
|
getUploadSpeed: function() { return this.fields.rateUpload; },
|
||||||
getUploadRatio: function() { return this.fields.uploadRatio; },
|
getUploadRatio: function() { return this.fields.uploadRatio; },
|
||||||
getUploadedEver: function() { return this.fields.uploadedEver; },
|
getUploadedEver: function() { return this.fields.uploadedEver; },
|
||||||
@@ -275,7 +278,6 @@ Torrent.prototype =
|
|||||||
default: return 'error';
|
default: return 'error';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
trackerStats: function() { return this._trackerStats; },
|
|
||||||
seedRatioLimit: function(controller){
|
seedRatioLimit: function(controller){
|
||||||
switch(this.getSeedRatioMode()) {
|
switch(this.getSeedRatioMode()) {
|
||||||
case Torrent._RatioUseGlobal: return controller.seedRatioLimit();
|
case Torrent._RatioUseGlobal: return controller.seedRatioLimit();
|
||||||
@@ -362,8 +364,14 @@ Torrent.compareById = function(ta, tb)
|
|||||||
};
|
};
|
||||||
Torrent.compareByName = function(ta, tb)
|
Torrent.compareByName = function(ta, tb)
|
||||||
{
|
{
|
||||||
return ta.getCollatedName().compareTo(tb.getCollatedName())
|
var i = 0;
|
||||||
|| Torrent.compareById(ta, tb);
|
var a = ta.getCollatedName();
|
||||||
|
var b = tb.getCollatedName();
|
||||||
|
if (a && b)
|
||||||
|
i = a.compareTo(b);
|
||||||
|
if (i)
|
||||||
|
return i;
|
||||||
|
return Torrent.compareById(ta, tb);
|
||||||
};
|
};
|
||||||
Torrent.compareByQueue = function(ta, tb)
|
Torrent.compareByQueue = function(ta, tb)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -68,13 +68,13 @@ Transmission.prototype =
|
|||||||
$('#torrent_upload_form').submit(function() { $('#upload_confirm_button').click(); return false; });
|
$('#torrent_upload_form').submit(function() { $('#upload_confirm_button').click(); return false; });
|
||||||
|
|
||||||
if (iPhone) {
|
if (iPhone) {
|
||||||
$('#inspector_close').bind('click', function() { tr.hideInspector(); });
|
$('#inspector_close').bind('click', function() { tr.setInspectorVisible(false); });
|
||||||
$('#preferences_link').bind('click', function(e) { tr.releaseClutchPreferencesButton(e); });
|
$('#preferences_link').bind('click', function(e) { tr.releaseClutchPreferencesButton(e); });
|
||||||
} else {
|
} else {
|
||||||
$(document).bind('keydown', function(e) { tr.keyDown(e); });
|
$(document).bind('keydown', function(e) { tr.keyDown(e); });
|
||||||
$(document).bind('keyup', function(e) { tr.keyUp(e); });
|
$(document).bind('keyup', function(e) { tr.keyUp(e); });
|
||||||
$('#torrent_container').click(function() { tr.deselectAll(true); });
|
$('#torrent_container').click(function() { tr.deselectAll(true); });
|
||||||
$('#inspector_link').click(function(e) { tr.toggleInspectorClicked(e); });
|
$('#inspector_link').click(function(e) { tr.toggleInspector(); });
|
||||||
|
|
||||||
this.setupSearchBox();
|
this.setupSearchBox();
|
||||||
this.createContextMenu();
|
this.createContextMenu();
|
||||||
@@ -86,7 +86,6 @@ Transmission.prototype =
|
|||||||
this._inspector_file_list = $('#inspector_file_list')[0];
|
this._inspector_file_list = $('#inspector_file_list')[0];
|
||||||
this._inspector_peers_list = $('#inspector_peers_list')[0];
|
this._inspector_peers_list = $('#inspector_peers_list')[0];
|
||||||
this._inspector_trackers_list = $('#inspector_trackers_list')[0];
|
this._inspector_trackers_list = $('#inspector_trackers_list')[0];
|
||||||
this._inspector_tab_files = $('#inspector_tab_files')[0];
|
|
||||||
this._toolbar_buttons = $('#toolbar ul li');
|
this._toolbar_buttons = $('#toolbar ul li');
|
||||||
this._toolbar_pause_button = $('#toolbar #pause_selected')[0];
|
this._toolbar_pause_button = $('#toolbar #pause_selected')[0];
|
||||||
this._toolbar_pause_all_button = $('#toolbar #pause_all')[0];
|
this._toolbar_pause_all_button = $('#toolbar #pause_all')[0];
|
||||||
@@ -221,7 +220,7 @@ Transmission.prototype =
|
|||||||
$('#reverse_sort_order').selectMenuItem();
|
$('#reverse_sort_order').selectMenuItem();
|
||||||
|
|
||||||
if (!iPhone && this[Prefs._ShowInspector])
|
if (!iPhone && this[Prefs._ShowInspector])
|
||||||
this.showInspector();
|
this.setInspectorVisible(true);
|
||||||
|
|
||||||
this.initCompactMode();
|
this.initCompactMode();
|
||||||
},
|
},
|
||||||
@@ -473,6 +472,9 @@ Transmission.prototype =
|
|||||||
|
|
||||||
selectionChanged: function()
|
selectionChanged: function()
|
||||||
{
|
{
|
||||||
|
if (this[Prefs._ShowInspector])
|
||||||
|
this.refreshInspectorTorrents(true);
|
||||||
|
|
||||||
this.updateButtonStates();
|
this.updateButtonStates();
|
||||||
this.updateInspector();
|
this.updateInspector();
|
||||||
this.updateSelectedData();
|
this.updateSelectedData();
|
||||||
@@ -719,11 +721,6 @@ Transmission.prototype =
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleInspectorClicked: function(ev) {
|
|
||||||
if (this.isButtonEnabled(ev))
|
|
||||||
this.toggleInspector();
|
|
||||||
},
|
|
||||||
|
|
||||||
inspectorTabClicked: function(ev, tab) {
|
inspectorTabClicked: function(ev, tab) {
|
||||||
if (iPhone) ev.stopPropagation();
|
if (iPhone) ev.stopPropagation();
|
||||||
|
|
||||||
@@ -740,19 +737,19 @@ Transmission.prototype =
|
|||||||
},
|
},
|
||||||
|
|
||||||
filesSelectAllClicked: function() {
|
filesSelectAllClicked: function() {
|
||||||
var t = this._files_torrent;
|
var t = this._file_torrent;
|
||||||
if (t)
|
if (t)
|
||||||
this.toggleFilesWantedDisplay(t, true);
|
this.toggleFilesWantedDisplay(t, true);
|
||||||
},
|
},
|
||||||
filesDeselectAllClicked: function() {
|
filesDeselectAllClicked: function() {
|
||||||
var t = this._files_torrent;
|
var t = this._file_torrent;
|
||||||
if (t)
|
if (t)
|
||||||
this.toggleFilesWantedDisplay(t, false);
|
this.toggleFilesWantedDisplay(t, false);
|
||||||
},
|
},
|
||||||
toggleFilesWantedDisplay: function(torrent, wanted) {
|
toggleFilesWantedDisplay: function(torrent, wanted) {
|
||||||
var rows = [ ];
|
var rows = [ ];
|
||||||
for (var i=0, row; row=this._files[i]; ++i)
|
for (var i=0, row; row=this._file_rows[i]; ++i)
|
||||||
if (row.isEditable() && (torrent._files[i].wanted !== wanted))
|
if (row.isEditable() && (torrent.getFile(i).wanted !== wanted))
|
||||||
rows.push(row);
|
rows.push(row);
|
||||||
if (rows.length > 0) {
|
if (rows.length > 0) {
|
||||||
var command = wanted ? 'files-wanted' : 'files-unwanted';
|
var command = wanted ? 'files-wanted' : 'files-unwanted';
|
||||||
@@ -1144,7 +1141,7 @@ Transmission.prototype =
|
|||||||
|
|
||||||
var torrents = this.getSelectedTorrents();
|
var torrents = this.getSelectedTorrents();
|
||||||
if (!torrents.length && iPhone) {
|
if (!torrents.length && iPhone) {
|
||||||
this.hideInspector();
|
this.setInspectorVisible(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1302,137 +1299,149 @@ Transmission.prototype =
|
|||||||
}
|
}
|
||||||
this.changeFileCommand(command, [ row ]);
|
this.changeFileCommand(command, [ row ]);
|
||||||
},
|
},
|
||||||
clearFileList: function() {
|
clearFileList: function()
|
||||||
|
{
|
||||||
$(this._inspector_file_list).empty();
|
$(this._inspector_file_list).empty();
|
||||||
delete this._files_torrent;
|
delete this._file_torrent;
|
||||||
delete this._files;
|
delete this._file_rows;
|
||||||
},
|
},
|
||||||
updateFileList: function() {
|
updateFileList: function()
|
||||||
|
{
|
||||||
|
if (!$(this._inspector_file_list).is(':visible'))
|
||||||
|
return;
|
||||||
|
|
||||||
// if the file list is hidden, clear the list
|
var sel = this.getSelectedTorrents();
|
||||||
if (this._inspector_tab_files.className.indexOf('selected') == -1) {
|
if (sel.length !== 1) {
|
||||||
this.clearFileList();
|
this.clearFileList();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if not torrent is selected, clear the list
|
var torrent = sel[0];
|
||||||
var selected_torrents = this.getSelectedTorrents();
|
if (torrent === this._files_torrent)
|
||||||
if (selected_torrents.length != 1) {
|
if(torrent.getFileCount() === (this._files ? this._files.length: 0))
|
||||||
this.clearFileList();
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the active torrent hasn't changed, noop
|
|
||||||
var torrent = selected_torrents[0];
|
|
||||||
if (this._files_torrent === torrent)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// build the file list
|
// build the file list
|
||||||
this.clearFileList();
|
this.clearFileList();
|
||||||
this._files_torrent = torrent;
|
this._file_torrent = torrent;
|
||||||
var n = torrent._files.length;
|
var n = torrent.getFileCount();
|
||||||
this._files = new Array(n);
|
this._file_rows = [];
|
||||||
var fragment = document.createDocumentFragment();
|
var fragment = document.createDocumentFragment();
|
||||||
var tr = this;
|
var tr = this;
|
||||||
for (var i=0; i<n; ++i) {
|
for (var i=0; i<n; ++i) {
|
||||||
var row = new FileRow(torrent, i);
|
var row = this._file_rows[i] = new FileRow(torrent, i);
|
||||||
fragment.appendChild(row.getElement());
|
fragment.appendChild(row.getElement());
|
||||||
this._files[i] = row;
|
|
||||||
$(row).bind('wantedToggled',function(e,row,want) {tr.onFileWantedToggled(row,want);});
|
$(row).bind('wantedToggled',function(e,row,want) {tr.onFileWantedToggled(row,want);});
|
||||||
$(row).bind('priorityToggled',function(e,row,priority) {tr.onFilePriorityToggled(row,priority);});
|
$(row).bind('priorityToggled',function(e,row,priority) {tr.onFilePriorityToggled(row,priority);});
|
||||||
}
|
}
|
||||||
this._inspector_file_list.appendChild(fragment);
|
this._inspector_file_list.appendChild(fragment);
|
||||||
},
|
},
|
||||||
|
|
||||||
refreshFileView: function() {
|
updatePeersLists: function()
|
||||||
for (var i=0, row; row=this._files[i]; ++i)
|
{
|
||||||
row.refresh();
|
if (!$(this._inspector_peers_list).is(':visible'))
|
||||||
},
|
return;
|
||||||
|
|
||||||
updatePeersLists: function() {
|
|
||||||
var html = [ ];
|
var html = [ ];
|
||||||
var fmt = Transmission.fmt;
|
var fmt = Transmission.fmt;
|
||||||
var torrents = this.getSelectedTorrents();
|
var torrents = this.getSelectedTorrents();
|
||||||
if ($(this._inspector_peers_list).is(':visible')) {
|
|
||||||
for (var k=0, torrent; torrent=torrents[k]; ++k) {
|
for (var k=0, torrent; torrent=torrents[k]; ++k) {
|
||||||
var peers = torrent.getPeers();
|
var peers = torrent.getPeers();
|
||||||
html.push('<div class="inspector_group">');
|
html.push('<div class="inspector_group">');
|
||||||
if (torrents.length > 1) {
|
if (torrents.length > 1) {
|
||||||
html.push('<div class="inspector_torrent_label">', torrent.getName(), '</div>');
|
html.push('<div class="inspector_torrent_label">', torrent.getName(), '</div>');
|
||||||
}
|
|
||||||
if (peers.length == 0) {
|
|
||||||
html.push('<br></div>'); // firefox won't paint the top border if the div is empty
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
html.push('<table class="peer_list">',
|
|
||||||
'<tr class="inspector_peer_entry even">',
|
|
||||||
'<th class="encryptedCol"></th>',
|
|
||||||
'<th class="upCol">Up</th>',
|
|
||||||
'<th class="downCol">Down</th>',
|
|
||||||
'<th class="percentCol">%</th>',
|
|
||||||
'<th class="statusCol">Status</th>',
|
|
||||||
'<th class="addressCol">Address</th>',
|
|
||||||
'<th class="clientCol">Client</th>',
|
|
||||||
'</tr>');
|
|
||||||
for (var i=0, peer; peer=peers[i]; ++i) {
|
|
||||||
var parity = ((i+1) % 2 == 0 ? 'even' : 'odd');
|
|
||||||
html.push('<tr class="inspector_peer_entry ', parity, '">',
|
|
||||||
'<td>', (peer.isEncrypted ? '<img src="images/graphics/lock_icon.png" alt="Encrypted"/>' : ''), '</td>',
|
|
||||||
'<td>', (peer.rateToPeer ? fmt.speedBps(peer.rateToPeer) : ''), '</td>',
|
|
||||||
'<td>', (peer.rateToClient ? fmt.speedBps(peer.rateToClient) : ''), '</td>',
|
|
||||||
'<td class="percentCol">', Math.floor(peer.progress*100), '%', '</td>',
|
|
||||||
'<td>', fmt.peerStatus(peer.flagStr), '</td>',
|
|
||||||
'<td>', peer.address, '</td>',
|
|
||||||
'<td class="clientCol">', peer.clientName, '</td>',
|
|
||||||
'</tr>');
|
|
||||||
}
|
|
||||||
html.push('</table></div>');
|
|
||||||
}
|
}
|
||||||
|
if (!peers || !peers.length) {
|
||||||
|
html.push('<br></div>'); // firefox won't paint the top border if the div is empty
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
html.push('<table class="peer_list">',
|
||||||
|
'<tr class="inspector_peer_entry even">',
|
||||||
|
'<th class="encryptedCol"></th>',
|
||||||
|
'<th class="upCol">Up</th>',
|
||||||
|
'<th class="downCol">Down</th>',
|
||||||
|
'<th class="percentCol">%</th>',
|
||||||
|
'<th class="statusCol">Status</th>',
|
||||||
|
'<th class="addressCol">Address</th>',
|
||||||
|
'<th class="clientCol">Client</th>',
|
||||||
|
'</tr>');
|
||||||
|
for (var i=0, peer; peer=peers[i]; ++i) {
|
||||||
|
var parity = ((i+1) % 2 == 0 ? 'even' : 'odd');
|
||||||
|
html.push('<tr class="inspector_peer_entry ', parity, '">',
|
||||||
|
'<td>', (peer.isEncrypted ? '<img src="images/graphics/lock_icon.png" alt="Encrypted"/>' : ''), '</td>',
|
||||||
|
'<td>', (peer.rateToPeer ? fmt.speedBps(peer.rateToPeer) : ''), '</td>',
|
||||||
|
'<td>', (peer.rateToClient ? fmt.speedBps(peer.rateToClient) : ''), '</td>',
|
||||||
|
'<td class="percentCol">', Math.floor(peer.progress*100), '%', '</td>',
|
||||||
|
'<td>', fmt.peerStatus(peer.flagStr), '</td>',
|
||||||
|
'<td>', peer.address, '</td>',
|
||||||
|
'<td class="clientCol">', peer.clientName, '</td>',
|
||||||
|
'</tr>');
|
||||||
|
}
|
||||||
|
html.push('</table></div>');
|
||||||
}
|
}
|
||||||
|
|
||||||
setInnerHTML(this._inspector_peers_list, html.join(''));
|
setInnerHTML(this._inspector_peers_list, html.join(''));
|
||||||
},
|
},
|
||||||
|
|
||||||
updateTrackersLists: function() {
|
updateTrackersLists: function() {
|
||||||
// By building up the HTML as as string, then have the browser
|
if (!$(this._inspector_trackers_list).is(':visible'))
|
||||||
// turn this into a DOM tree, this is a fast operation.
|
return;
|
||||||
|
|
||||||
var tr = this;
|
var tr = this;
|
||||||
var html = [ ];
|
var html = [ ];
|
||||||
var na = 'N/A';
|
var na = 'N/A';
|
||||||
var torrents = this.getSelectedTorrents();
|
var torrents = this.getSelectedTorrents();
|
||||||
if ($(this._inspector_trackers_list).is(':visible')) {
|
|
||||||
for (var k=0, torrent; torrent = torrents[k]; ++k) {
|
|
||||||
html.push ('<div class="inspector_group">');
|
|
||||||
if (torrents.length > 1) {
|
|
||||||
html.push('<div class="inspector_torrent_label">', torrent.getName(), '</div>');
|
|
||||||
}
|
|
||||||
for (var i=0, tier; tier=torrent._trackerStats[i]; ++i) {
|
|
||||||
html.push('<div class="inspector_group_label">',
|
|
||||||
'Tier ', (i + 1), '</div>',
|
|
||||||
'<ul class="tier_list">');
|
|
||||||
for (var j=0, tracker; tracker=tier[j]; ++j) {
|
|
||||||
var lastAnnounceStatusHash = tr.lastAnnounceStatus(tracker);
|
|
||||||
var announceState = tr.announceState(tracker);
|
|
||||||
var lastScrapeStatusHash = tr.lastScrapeStatus(tracker);
|
|
||||||
|
|
||||||
// Display construction
|
// By building up the HTML as as string, then have the browser
|
||||||
var parity = ((j+1) % 2 == 0 ? 'even' : 'odd');
|
// turn this into a DOM tree, this is a fast operation.
|
||||||
html.push('<li class="inspector_tracker_entry ', parity, '"><div class="tracker_host" title="', tracker.announce, '">',
|
for (var i=0, torrent; torrent=torrents[i]; ++i)
|
||||||
tracker.host, '</div>',
|
{
|
||||||
'<div class="tracker_activity">',
|
html.push ('<div class="inspector_group">');
|
||||||
'<div>', lastAnnounceStatusHash['label'], ': ', lastAnnounceStatusHash['value'], '</div>',
|
|
||||||
'<div>', announceState, '</div>',
|
if (torrents.length > 1)
|
||||||
'<div>', lastScrapeStatusHash['label'], ': ', lastScrapeStatusHash['value'], '</div>',
|
html.push('<div class="inspector_torrent_label">', torrent.getName(), '</div>');
|
||||||
'</div><table class="tracker_stats">',
|
|
||||||
'<tr><th>Seeders:</th><td>', (tracker.seederCount > -1 ? tracker.seederCount : na), '</td></tr>',
|
var tier = -1;
|
||||||
'<tr><th>Leechers:</th><td>', (tracker.leecherCount > -1 ? tracker.leecherCount : na), '</td></tr>',
|
var trackers = torrent.getTrackers();
|
||||||
'<tr><th>Downloads:</th><td>', (tracker.downloadCount > -1 ? tracker.downloadCount : na), '</td></tr>',
|
for (var j=0, tracker; tracker=trackers[j]; ++j)
|
||||||
'</table></li>');
|
{
|
||||||
}
|
if (tier != tracker.tier)
|
||||||
html.push('</ul>');
|
{
|
||||||
|
if (tier !== -1) // close previous tier
|
||||||
|
html.push('</ul></div>');
|
||||||
|
|
||||||
|
tier = tracker.tier;
|
||||||
|
|
||||||
|
html.push('<div class="inspector_group_label">',
|
||||||
|
'Tier ', tier, '</div>',
|
||||||
|
'<ul class="tier_list">');
|
||||||
}
|
}
|
||||||
html.push('</div>');
|
|
||||||
|
var lastAnnounceStatusHash = tr.lastAnnounceStatus(tracker);
|
||||||
|
var announceState = tr.announceState(tracker);
|
||||||
|
var lastScrapeStatusHash = tr.lastScrapeStatus(tracker);
|
||||||
|
|
||||||
|
// Display construction
|
||||||
|
var parity = ((j+1) % 2 == 0 ? 'even' : 'odd');
|
||||||
|
html.push('<li class="inspector_tracker_entry ', parity, '"><div class="tracker_host" title="', tracker.announce, '">',
|
||||||
|
tracker.host, '</div>',
|
||||||
|
'<div class="tracker_activity">',
|
||||||
|
'<div>', lastAnnounceStatusHash['label'], ': ', lastAnnounceStatusHash['value'], '</div>',
|
||||||
|
'<div>', announceState, '</div>',
|
||||||
|
'<div>', lastScrapeStatusHash['label'], ': ', lastScrapeStatusHash['value'], '</div>',
|
||||||
|
'</div><table class="tracker_stats">',
|
||||||
|
'<tr><th>Seeders:</th><td>', (tracker.seederCount > -1 ? tracker.seederCount : na), '</td></tr>',
|
||||||
|
'<tr><th>Leechers:</th><td>', (tracker.leecherCount > -1 ? tracker.leecherCount : na), '</td></tr>',
|
||||||
|
'<tr><th>Downloads:</th><td>', (tracker.downloadCount > -1 ? tracker.downloadCount : na), '</td></tr>',
|
||||||
|
'</table></li>');
|
||||||
}
|
}
|
||||||
|
if (tier !== -1) // close last tier
|
||||||
|
html.push('</ul></div>');
|
||||||
|
|
||||||
|
html.push('</div>'); // inspector_group
|
||||||
}
|
}
|
||||||
|
|
||||||
setInnerHTML(this._inspector_trackers_list, html.join(''));
|
setInnerHTML(this._inspector_trackers_list, html.join(''));
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1493,128 +1502,95 @@ Transmission.prototype =
|
|||||||
return {'label':lastScrapeLabel, 'value':lastScrape};
|
return {'label':lastScrapeLabel, 'value':lastScrape};
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
toggleInspector: function()
|
||||||
* Toggle the visibility of the inspector (used by the context menu)
|
{
|
||||||
*/
|
this.setInspectorVisible(!this[Prefs._ShowInspector]);
|
||||||
toggleInspector: function() {
|
|
||||||
if (this[Prefs._ShowInspector])
|
|
||||||
this.hideInspector();
|
|
||||||
else
|
|
||||||
this.showInspector();
|
|
||||||
},
|
},
|
||||||
|
setInspectorVisible: function(visible)
|
||||||
|
{
|
||||||
|
// we collect extra stats on torrents when they're in the inspector...
|
||||||
|
clearInterval(this._periodic_inspector_refresh);
|
||||||
|
delete this._periodic_inspector_refresh;
|
||||||
|
if (visible) {
|
||||||
|
var tr = this;
|
||||||
|
this._periodic_inspector_refresh = setInterval(function() {tr.refreshInspectorTorrents(false);},2000);
|
||||||
|
this.refreshInspectorTorrents(true);
|
||||||
|
}
|
||||||
|
|
||||||
showInspector: function() {
|
// update the ui widgetry
|
||||||
$('#torrent_inspector').show();
|
$('#torrent_inspector').toggle(visible);
|
||||||
if (iPhone) {
|
if (iPhone) {
|
||||||
$('body').addClass('inspector_showing');
|
$('body').toggleClass('inspector_showing',visible);
|
||||||
$('#inspector_close').show();
|
$('#inspector_close').toggle(visible);
|
||||||
this.hideiPhoneAddressbar();
|
this.hideiPhoneAddressbar();
|
||||||
} else {
|
} else {
|
||||||
var w = $('#torrent_inspector').width() + 1 + 'px';
|
var w = visible ? $('#torrent_inspector').width() + 1 + 'px' : '0px';
|
||||||
$('#torrent_container')[0].style.right = w;
|
$('#torrent_container')[0].style.right = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
setInnerHTML($('ul li#context_toggle_inspector')[0], 'Hide Inspector');
|
setInnerHTML($('ul li#context_toggle_inspector')[0], (visible?'Hide':'Show')+' Inspector');
|
||||||
|
this.setPref(Prefs._ShowInspector, visible);
|
||||||
this.setPref(Prefs._ShowInspector, true);
|
if (visible)
|
||||||
this.updateInspector();
|
this.updateInspector();
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
onTorrentChanged: function(ev)
|
||||||
* Hide the inspector
|
{
|
||||||
*/
|
this.refilterSoon();
|
||||||
hideInspector: function() {
|
|
||||||
|
// if this torrent is in the inspector, refresh the inspector
|
||||||
|
if (this[Prefs._ShowInspector])
|
||||||
|
if (this.getSelectedTorrentIds().indexOf(ev.target.getId()) !== -1)
|
||||||
|
this.updateInspector();
|
||||||
|
},
|
||||||
|
|
||||||
$('#torrent_inspector').hide();
|
updateFromTorrentGet: function(updates, removed_ids)
|
||||||
|
{
|
||||||
|
var new_ids = [];
|
||||||
|
|
||||||
if (iPhone) {
|
for (var i=0, o; o=updates[i]; ++i) {
|
||||||
this.deselectAll();
|
var t;
|
||||||
$('body.inspector_showing').removeClass('inspector_showing');
|
var id = o.id;
|
||||||
$('#inspector_close').hide();
|
if ((t = this._torrents[id]))
|
||||||
this.hideiPhoneAddressbar();
|
t.refresh(o);
|
||||||
} else {
|
else {
|
||||||
$('#torrent_container')[0].style.right = '0px';
|
t = this._torrents[id] = new Torrent(o);
|
||||||
setInnerHTML($('ul li#context_toggle_inspector')[0], 'Show Inspector');
|
$(t).bind('dataChanged',function(ev) {tr.onTorrentChanged(ev);});
|
||||||
|
new_ids.push(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setPref(Prefs._ShowInspector, false);
|
if (new_ids.length) {
|
||||||
},
|
var tr = this;
|
||||||
|
this.remote.getTorrentInitial(new_ids, function(a,b){tr.updateFromTorrentGet(a,b);});
|
||||||
|
this.refilterSoon();
|
||||||
|
}
|
||||||
|
|
||||||
refreshMetaData: function(ids) {
|
if (removed_ids) {
|
||||||
var tr = this;
|
this.deleteTorrents(removed_ids);
|
||||||
this.remote.getMetaDataFor(ids, function(active) { tr.updateMetaData(active); });
|
this.refilterSoon();
|
||||||
},
|
}
|
||||||
|
|
||||||
updateMetaData: function(torrents)
|
|
||||||
{
|
|
||||||
var tr = this;
|
|
||||||
var refresh_files_for = [ ];
|
|
||||||
var selected_torrents = this.getSelectedTorrents();
|
|
||||||
jQuery.each(torrents, function() {
|
|
||||||
var t = tr._torrents[ this.id ];
|
|
||||||
if (t) {
|
|
||||||
t.refreshMetaData(this);
|
|
||||||
if (selected_torrents.indexOf(t) != -1)
|
|
||||||
refresh_files_for.push(t.getId());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (refresh_files_for.length > 0)
|
|
||||||
tr.remote.loadTorrentFiles(refresh_files_for);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
refreshTorrents: function(ids) {
|
refreshTorrents: function(ids) {
|
||||||
var tr = this;
|
|
||||||
if (!ids)
|
if (!ids)
|
||||||
ids = 'recently-active';
|
ids = 'recently-active';
|
||||||
|
|
||||||
this.remote.getUpdatedDataFor(ids, function(active, removed) { tr.updateTorrentsData(active, removed); });
|
|
||||||
},
|
|
||||||
|
|
||||||
updateTorrentsData: function(updated, removed_ids) {
|
|
||||||
var tr = this;
|
var tr = this;
|
||||||
var new_torrent_ids = [];
|
this.remote.getTorrentStats(ids, function(a,b){tr.updateFromTorrentGet(a,b);});
|
||||||
var refresh_files_for = [];
|
|
||||||
var selected_torrents = this.getSelectedTorrents();
|
|
||||||
|
|
||||||
for (var i=0, o; o=updated[i]; ++i) {
|
|
||||||
var t = tr._torrents[o.id];
|
|
||||||
if (t == null)
|
|
||||||
new_torrent_ids.push(o.id);
|
|
||||||
else {
|
|
||||||
t.refresh(o);
|
|
||||||
if (selected_torrents.indexOf(t) != -1)
|
|
||||||
refresh_files_for.push(t.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (refresh_files_for.length > 0)
|
|
||||||
tr.remote.loadTorrentFiles(refresh_files_for);
|
|
||||||
|
|
||||||
if (new_torrent_ids.length > 0)
|
|
||||||
tr.remote.getInitialDataFor(new_torrent_ids, function(torrents) {tr.addTorrents(torrents);});
|
|
||||||
|
|
||||||
tr.deleteTorrents(removed_ids);
|
|
||||||
|
|
||||||
if (new_torrent_ids.length != 0) {
|
|
||||||
tr.hideiPhoneAddressbar();
|
|
||||||
tr.deselectAll(true);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
updateTorrentsFileData: function(torrents) {
|
|
||||||
for (var i=0, o; o=torrents[i]; ++i) {
|
|
||||||
var t = this._torrents[o.id];
|
|
||||||
if (t) {
|
|
||||||
t.refreshFiles(o);
|
|
||||||
if (t === this._files_torrent)
|
|
||||||
this.refreshFileView();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
initializeAllTorrents: function() {
|
initializeAllTorrents: function() {
|
||||||
var tr = this;
|
var tr = this;
|
||||||
this.remote.getInitialDataFor(null ,function(torrents) { tr.addTorrents(torrents); });
|
this.remote.getTorrentInitial(null, function(a,b){tr.updateFromTorrentGet(a,b);});
|
||||||
|
},
|
||||||
|
refreshMetadata: function(ids) {
|
||||||
|
var tr = this;
|
||||||
|
this.remote.getTorrentMetadata(ids, function(a,b){tr.updateFromTorrentGet(a,b);});
|
||||||
|
},
|
||||||
|
refreshInspectorTorrents: function(full) {
|
||||||
|
var tr = this;
|
||||||
|
var ids = tr.getSelectedTorrentIds();
|
||||||
|
if (ids.length > 0)
|
||||||
|
this.remote.getTorrentDetails(ids, full, function(a,b){tr.updateFromTorrentGet(a,b);});
|
||||||
},
|
},
|
||||||
|
|
||||||
onRowClicked: function(ev, row)
|
onRowClicked: function(ev, row)
|
||||||
@@ -1634,7 +1610,7 @@ Transmission.prototype =
|
|||||||
// Shift-Click - selects a range from the last-clicked row to this one
|
// Shift-Click - selects a range from the last-clicked row to this one
|
||||||
if (iPhone) {
|
if (iPhone) {
|
||||||
if (row.isSelected())
|
if (row.isSelected())
|
||||||
this.showInspector();
|
this.setInspectorVisible(true);
|
||||||
this.setSelectedRow(row);
|
this.setSelectedRow(row);
|
||||||
|
|
||||||
} else if (ev.shiftKey) {
|
} else if (ev.shiftKey) {
|
||||||
@@ -1662,20 +1638,6 @@ Transmission.prototype =
|
|||||||
this._last_torrent_clicked = row.getTorrent().getId();
|
this._last_torrent_clicked = row.getTorrent().getId();
|
||||||
},
|
},
|
||||||
|
|
||||||
addTorrents: function(new_torrents)
|
|
||||||
{
|
|
||||||
var tr = this;
|
|
||||||
var key = 'dataChanged';
|
|
||||||
|
|
||||||
for (var i=0, row; row=new_torrents[i]; ++i) {
|
|
||||||
var t = new Torrent(row);
|
|
||||||
$(t).bind(key,function() {tr.refilterSoon();});
|
|
||||||
this._torrents[t.getId()] = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.refilterSoon();
|
|
||||||
},
|
|
||||||
|
|
||||||
deleteTorrents: function(torrent_ids)
|
deleteTorrents: function(torrent_ids)
|
||||||
{
|
{
|
||||||
if (torrent_ids && torrent_ids.length)
|
if (torrent_ids && torrent_ids.length)
|
||||||
@@ -2197,27 +2159,26 @@ Transmission.prototype =
|
|||||||
|
|
||||||
getTrackers: function()
|
getTrackers: function()
|
||||||
{
|
{
|
||||||
var trackers = {};
|
var ret = {};
|
||||||
|
|
||||||
var torrents = this.getAllTorrents();
|
var torrents = this.getAllTorrents();
|
||||||
for (var i=0, torrent; torrent=torrents[i]; ++i) {
|
for (var i=0, torrent; torrent=torrents[i]; ++i) {
|
||||||
var names = [];
|
var names = [];
|
||||||
for (var j=0, tier; tier=torrent._trackerStats[j]; ++j) {
|
var trackers = torrent.getTrackers();
|
||||||
for (var k=0, tracker; tracker=tier[k]; ++k) {
|
for (var j=0, tracker; tracker=trackers[j]; ++j) {
|
||||||
var uri = parseUri(tracker.announce);
|
var uri = parseUri(tracker.announce);
|
||||||
var domain = this.getDomainName(uri.host);
|
var domain = this.getDomainName(uri.host);
|
||||||
var name = this.getReadableDomain(domain);
|
var name = this.getReadableDomain(domain);
|
||||||
if (!(name in trackers))
|
if (!(name in ret))
|
||||||
trackers[name] = { 'uri': uri, 'domain': domain, 'count': 0 };
|
ret[name] = { 'uri': uri, 'domain': domain, 'count': 0 };
|
||||||
if (names.indexOf(name) === -1)
|
if (names.indexOf(name) === -1)
|
||||||
names.push(name);
|
names.push(name);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (var j=0, name; name=names[j]; ++j)
|
for (var j=0, name; name=names[j]; ++j)
|
||||||
trackers[name].count++;
|
ret[name].count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return trackers;
|
return ret;
|
||||||
},
|
},
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
|||||||
@@ -30,20 +30,20 @@ RPC._TurtleTimeEnd = 'alt-speed-time-end';
|
|||||||
RPC._TurtleTimeDay = 'alt-speed-time-day';
|
RPC._TurtleTimeDay = 'alt-speed-time-day';
|
||||||
RPC._PeerLimitGlobal = 'peer-limit-global';
|
RPC._PeerLimitGlobal = 'peer-limit-global';
|
||||||
RPC._PeerLimitPerTorrent = 'peer-limit-per-torrent';
|
RPC._PeerLimitPerTorrent = 'peer-limit-per-torrent';
|
||||||
RPC._PexEnabled = 'pex-enabled';
|
RPC._PexEnabled = 'pex-enabled';
|
||||||
RPC._DhtEnabled = 'dht-enabled';
|
RPC._DhtEnabled = 'dht-enabled';
|
||||||
RPC._LpdEnabled = 'lpd-enabled';
|
RPC._LpdEnabled = 'lpd-enabled';
|
||||||
RPC._BlocklistEnabled = 'blocklist-enabled';
|
RPC._BlocklistEnabled = 'blocklist-enabled';
|
||||||
RPC._BlocklistURL = 'blocklist-url';
|
RPC._BlocklistURL = 'blocklist-url';
|
||||||
RPC._BlocklistSize = 'blocklist-size';
|
RPC._BlocklistSize = 'blocklist-size';
|
||||||
RPC._UtpEnabled = 'utp-enabled';
|
RPC._UtpEnabled = 'utp-enabled';
|
||||||
RPC._PeerPortRandom = 'peer-port-random-on-start';
|
RPC._PeerPortRandom = 'peer-port-random-on-start';
|
||||||
RPC._PortForwardingEnabled = 'port-forwarding-enabled';
|
RPC._PortForwardingEnabled = 'port-forwarding-enabled';
|
||||||
RPC._StartAddedTorrent = 'start-added-torrents';
|
RPC._StartAddedTorrent = 'start-added-torrents';
|
||||||
RPC._QueueMoveTop = 'queue-move-top';
|
RPC._QueueMoveTop = 'queue-move-top';
|
||||||
RPC._QueueMoveBottom = 'queue-move-bottom';
|
RPC._QueueMoveBottom = 'queue-move-bottom';
|
||||||
RPC._QueueMoveUp = 'queue-move-up';
|
RPC._QueueMoveUp = 'queue-move-up';
|
||||||
RPC._QueueMoveDown = 'queue-move-down';
|
RPC._QueueMoveDown = 'queue-move-down';
|
||||||
|
|
||||||
function TransmissionRemote(controller)
|
function TransmissionRemote(controller)
|
||||||
{
|
{
|
||||||
@@ -133,28 +133,25 @@ TransmissionRemote.prototype =
|
|||||||
this.sendRequest(o, callback, async);
|
this.sendRequest(o, callback, async);
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialDataFor: function(torrent_ids, callback) {
|
getTorrentInitial: function(torrent_ids, callback) {
|
||||||
var o = {
|
var o = {
|
||||||
method: 'torrent-get',
|
method: 'torrent-get',
|
||||||
arguments: {
|
arguments: {
|
||||||
fields: Torrent._StaticFields.concat(Torrent._MetaDataFields,
|
fields: ['id'].concat(Torrent.Fields.Metadata, Torrent.Fields.Stats)
|
||||||
Torrent._DynamicFields,
|
|
||||||
[ 'files', 'fileStats' ])
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (torrent_ids)
|
if (torrent_ids)
|
||||||
o.arguments.ids = torrent_ids;
|
o.arguments.ids = torrent_ids;
|
||||||
|
|
||||||
this.sendRequest(o, function(data){ callback(data.arguments.torrents);});
|
this.sendRequest(o, function(data){ callback(data.arguments.torrents, data.arguments.removed);});
|
||||||
},
|
},
|
||||||
|
|
||||||
getMetaDataFor: function(torrent_ids, callback) {
|
getTorrentMetadata: function(torrent_ids, callback) {
|
||||||
var o = {
|
var o = {
|
||||||
method: 'torrent-get',
|
method: 'torrent-get',
|
||||||
arguments: {
|
arguments: {
|
||||||
fields: Torrent._StaticFields.concat(Torrent._MetaDataFields,
|
fields: ['id'].concat(Torrent.Fields.Metadata)
|
||||||
['files', 'fileStats'])
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -164,26 +161,31 @@ TransmissionRemote.prototype =
|
|||||||
this.sendRequest(o, function(data) {callback(data.arguments.torrents)});
|
this.sendRequest(o, function(data) {callback(data.arguments.torrents)});
|
||||||
},
|
},
|
||||||
|
|
||||||
getUpdatedDataFor: function(torrent_ids, callback) {
|
getTorrentStats: function(torrent_ids, callback) {
|
||||||
var o = {
|
var o = {
|
||||||
method: 'torrent-get',
|
method: 'torrent-get',
|
||||||
arguments: {
|
arguments: {
|
||||||
'ids': torrent_ids,
|
'ids': torrent_ids,
|
||||||
fields: [ 'id' ].concat(Torrent._DynamicFields)
|
fields: ['id'].concat(Torrent.Fields.Stats)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.sendRequest(o, function(data) {callback(data.arguments.torrents, data.arguments.removed);});
|
this.sendRequest(o, function(data) {callback(data.arguments.torrents, data.arguments.removed);});
|
||||||
},
|
},
|
||||||
|
|
||||||
loadTorrentFiles: function(torrent_ids) {
|
/* called for the torrents in the inspector aka details dialog */
|
||||||
var tr = this._controller;
|
getTorrentDetails: function(torrent_ids, full, callback) {
|
||||||
this.sendRequest({
|
var f = ['id'].concat(Torrent.Fields.StatsExtra);
|
||||||
|
if (full) // these only need to be loaded once...
|
||||||
|
f = f.concat(Torrent.Fields.InfoExtra);
|
||||||
|
var o = {
|
||||||
method: 'torrent-get',
|
method: 'torrent-get',
|
||||||
arguments: { fields: [ 'id', 'fileStats'], ids: torrent_ids }
|
arguments: {
|
||||||
}, function(data) {
|
'ids': torrent_ids,
|
||||||
tr.updateTorrentsFileData(data.arguments.torrents);
|
fields: f,
|
||||||
});
|
}
|
||||||
|
};
|
||||||
|
this.sendRequest(o, function(data) {callback(data.arguments.torrents,null)});
|
||||||
},
|
},
|
||||||
|
|
||||||
changeFileCommand: function(command, rows) {
|
changeFileCommand: function(command, rows) {
|
||||||
|
|||||||
Reference in New Issue
Block a user