diff --git a/css/style.css b/css/style.css
index 522640b1c..6065abb62 100644
--- a/css/style.css
+++ b/css/style.css
@@ -96,6 +96,7 @@ div#CatList ul li.sel {background-color: #CFDEEF; border-color: #CFDEEF }
#-_-_-act-_-_- {background-position: 4px -158px;}
#-_-_-iac-_-_- {background-position: 4px -30px;}
#-_-_-err-_-_- {background-position: 4px -94px;}
+span.label-count,span.label-size { background-color: #F0F0F0; padding: 0.1em 0.3em 0.1em 0.3em; margin-left: 0.3em; border-radius: 0.8em; }
div#CatList ul li.RSS {background-image: url(../images/tstatus.png); background-position: 4px -206px}
div#CatList ul li.disRSS {background-image: url(../images/tstatus.png); background-position: 4px -190px}
diff --git a/index.html b/index.html
index f900ce55f..38e4d4f40 100644
--- a/index.html
+++ b/index.html
@@ -96,26 +96,34 @@
-
- (0)
+ 0
+
-
- (0)
+ 0
+
-
- (0)
+ 0
+
-
- (0)
+ 0
+
-
- (0)
+ 0
+
-
- (0)
+ 0
+
@@ -123,7 +131,8 @@
diff --git a/js/content.js b/js/content.js
index 12bf05c82..8ebff2251 100644
--- a/js/content.js
+++ b/js/content.js
@@ -337,9 +337,15 @@ function makeContent()
""+
""+
"
"+
+ ""+
+ ""+
+ "
"+
""+
""+
"
"+
+ ""+
+ ""+
+ "
"+
""+
""+
"
"+
diff --git a/js/rtorrent.js b/js/rtorrent.js
index 72a7fc2b0..fe8a965aa 100644
--- a/js/rtorrent.js
+++ b/js/rtorrent.js
@@ -1094,7 +1094,7 @@ rTorrentStub.prototype.listResponse = function(xml)
state|=dStatus.error;
torrent.state = state;
torrent.name = this.getValue(values,5);
- torrent.size = this.getValue(values,6);
+ torrent.size = iv(this.getValue(values,6));
var get_completed_chunks = parseInt(this.getValue(values,7));
var get_hashed_chunks = parseInt(this.getValue(values,25));
var get_size_chunks = parseInt(this.getValue(values,8));
@@ -1110,19 +1110,7 @@ rTorrentStub.prototype.listResponse = function(xml)
try {
torrent.label = decodeURIComponent(this.getValue(values,15)).trim();
} catch(e) { torrent.label = ''; }
- if(torrent.label.length>0)
- {
- if(!$type(ret.labels[torrent.label]))
- {
- ret.labels[torrent.label] = 1;
- ret.labels_size[torrent.label] = parseInt(torrent.size);
- }
- else
- {
- ret.labels[torrent.label]++;
- ret.labels_size[torrent.label] = parseInt(ret.labels_size[torrent.label]) + parseInt(torrent.size);
- }
- }
+
var get_peers_not_connected = parseInt(this.getValue(values,17));
var get_peers_connected = parseInt(this.getValue(values,18));
var get_peers_all = get_peers_not_connected+get_peers_connected;
diff --git a/js/webui.js b/js/webui.js
index 7c0a882ba..615ebb1c3 100644
--- a/js/webui.js
+++ b/js/webui.js
@@ -156,6 +156,8 @@ var theWebUI =
"webui.speedintitle": 0,
"webui.log_autoswitch": 1,
"webui.show_labelsize": 1,
+ "webui.show_searchlabelsize": 0,
+ "webui.show_statelabelsize": 0,
"webui.register_magnet": 0
},
showFlags: 0,
@@ -183,19 +185,21 @@ var theWebUI =
peers: {},
labels:
{
- "-_-_-all-_-_-": 0,
- "-_-_-dls-_-_-": 0,
- "-_-_-com-_-_-": 0,
- "-_-_-act-_-_-": 0,
- "-_-_-iac-_-_-": 0,
- "-_-_-nlb-_-_-": 0,
- "-_-_-err-_-_-": 0
+ "-_-_-all-_-_-": { cnt: 0, size: 0 },
+ "-_-_-dls-_-_-": { cnt: 0, size: 0 },
+ "-_-_-com-_-_-": { cnt: 0, size: 0 },
+ "-_-_-act-_-_-": { cnt: 0, size: 0 },
+ "-_-_-iac-_-_-": { cnt: 0, size: 0 },
+ "-_-_-nlb-_-_-": { cnt: 0, size: 0 },
+ "-_-_-err-_-_-": { cnt: 0, size: 0 }
},
actLbls:
{
"pstate_cont": ""
},
cLabels: {},
+ stateLabels: {},
+ staticLabels: ['dls','com','act','iac','nlb','err'],
dID: "",
pID: "",
speedGraph: new rSpeedGraph(),
@@ -1638,14 +1642,11 @@ var theWebUI =
* @property {StatusMask} state
* @property {number} done - number between 0..1000
* @property {number} size
- * @property {boolean} _updated
*/
/**
* @param {Object} data
- * @param {Array.} data.torrents
- * @param {Object.} data.labels
- * @param {Object.} data.labels_size
+ * @param {Object.} data.torrents
*/
addTorrents: function(data)
{
@@ -1709,45 +1710,47 @@ var theWebUI =
for( var prop in torrent)
table.setValueById(hash, prop, torrent[prop]);
}
- torrent._updated = true;
});
- $.extend(this.torrents,data.torrents);
- this.setSpeedValues(tul,tdl);
var wasRemoved = false;
- this.clearTegs();
- $.each(this.torrents,function(hash,torrent)
- {
- if(!torrent._updated)
- {
- delete theWebUI.torrents[hash];
+ for (var hash in this.torrents) {
+ // cleanup removed torrents
+ if (!(hash in data.torrents)) {
delete theWebUI.files[hash];
delete theWebUI.dirs[hash];
delete theWebUI.peers[hash];
- if(theWebUI.labels[hash].indexOf("-_-_-nlb-_-_-") >- 1)
- theWebUI.labels["-_-_-nlb-_-_-"]--;
- if(theWebUI.labels[hash].indexOf("-_-_-com-_-_-") >- 1)
- theWebUI.labels["-_-_-com-_-_-"]--;
- if(theWebUI.labels[hash].indexOf("-_-_-dls-_-_-") >- 1)
- theWebUI.labels["-_-_-dls-_-_-"]--;
- if(theWebUI.labels[hash].indexOf("-_-_-act-_-_-") >- 1)
- theWebUI.labels["-_-_-act-_-_-"]--;
- if(theWebUI.labels[hash].indexOf("-_-_-iac-_-_-") >- 1)
- theWebUI.labels["-_-_-iac-_-_-"]--;
- if(theWebUI.labels[hash].indexOf("-_-_-err-_-_-") >- 1)
- theWebUI.labels["-_-_-err-_-_-"]--;
delete theWebUI.labels[hash];
table.removeRow(hash);
wasRemoved = true;
}
- else
- {
- torrent._updated = false;
- theWebUI.updateTegs(torrent);
- }
- });
+ }
+ this.torrents = data.torrents;
+ this.setSpeedValues(tul,tdl);
this.getAllTrackers(tArray);
- this.loadLabels(data.labels, data.labels_size);
+
+ // sum up label sizes
+ var labelCount = {};
+ var labelSize = {};
+ this.allLabelSize = 0;
+ for (var lbl of this.staticLabels) {
+ labelCount[lbl] = 0;
+ labelSize[lbl] = 0;
+ }
+
+ for (var hash in this.torrents) {
+ var t = this.torrents[hash];
+ for (var lbl of (this.stateLabels[hash]||[]).concat(t.label.length ? [t.label] : [])) {
+ labelCount[lbl] = (labelCount[lbl]||0) + 1;
+ labelSize[lbl] = (labelSize[lbl]||0) + t.size;
+ }
+ this.allLabelSize += t.size;
+ }
+
+ this.loadLabels(labelCount, labelSize);
+ // update state and custom labels
this.updateLabels(wasRemoved);
+ // update search labels (tegs)
+ this.updateTegs(Object.values(this.tegs));
+ this.updateTegLabels(Object.keys(this.tegs));
this.loadTorrents();
this.getTotal();
@@ -1759,6 +1762,13 @@ var theWebUI =
data = null;
},
+ updateAllFilterLabel: function(labelType, showSize) {
+ this.updateLabel(
+ '#' + labelType + ' .-_-_-all-_-_-',
+ Object.keys(this.torrents).length,
+ this.allLabelSize, showSize);
+ },
+
setSpeedValues: function(tul,tdl)
{
this.speedGraph.addData(tul,tdl);
@@ -1875,14 +1885,13 @@ var theWebUI =
this.switchLabel($$(id));
return;
}
- var tegIg = "teg_"+this.lastTeg;
+ var tegId = "teg_"+this.lastTeg;
this.lastTeg++;
- var el = $("").attr("id",tegIg).addClass("teg").
- html(escapeHTML(str) + " (0)").attr("title",str+" (0)").
- mouseclick(theWebUI.tegContextMenu).addClass("cat")
+ var el = this.createSelectableLabelElement(tegId, str, theWebUI.tegContextMenu).addClass('teg');
$("#lblf").append( el );
- this.tegs[tegIg] = { val: str, cnt: 0 };
- this.updateTeg(tegIg);
+ this.tegs[tegId] = { val: str };
+ this.updateTegs([this.tegs[tegId]]);
+ this.updateTegLabels([tegId]);
this.resetLabels();
this.switchLabel(el[0]);
}
@@ -1892,45 +1901,35 @@ var theWebUI =
}
},
- clearTegs: function()
- {
- for( var id in this.tegs )
- this.tegs[id].cnt = 0;
- },
-
matchTeg: function(teg, name)
{
var pattern = teg.val.replace(/[-[\]{}()+?.,\\^$|#\s]/g, '\\$&');
return new RegExp(pattern.replace('*', '.+'), 'i').test(name);
},
- updateTeg: function(id)
+ updateTegs: function(tegObjs)
{
- var teg = this.tegs[id];
- var self = this;
- $.each(this.torrents,function(hash,torrent)
- {
- if(self.matchTeg(teg, torrent.name))
- teg.cnt++;
- });
- var counter = $("#"+id+"-c");
- if(counter.text()!=teg.cnt)
- {
- counter.text(teg.cnt);
- $("#"+id).prop("title",teg.val+" ("+teg.cnt+")");
+ for (var teg of tegObjs) {
+ teg.cnt = 0;
+ teg.size = 0;
+ }
+ for (var hash in this.torrents) {
+ var torrent = this.torrents[hash];
+ for (var teg of tegObjs) {
+ if(this.matchTeg(teg, torrent.name)) {
+ teg.cnt++;
+ teg.size += torrent.size;
+ }
+ }
}
},
- /**
- * @param {WebUITorrent} torrent
- */
- updateTegs: function(torrent)
+ updateTegLabels: function(tegIds)
{
- for( var id in this.tegs )
+ for( var id of tegIds )
{
var teg = this.tegs[id];
- if(this.matchTeg(teg, torrent.name))
- teg.cnt++;
+ this.updateLabel($$(id), teg.cnt, teg.size, this.settings["webui.show_searchlabelsize"]);
}
},
@@ -1966,7 +1965,7 @@ var theWebUI =
}
else
theContextMenu.clear();
- theContextMenu.add([theUILang.removeTeg, "theWebUI.removeTeg('"+e.target.id+"');"]);
+ theContextMenu.add([theUILang.removeTeg, "theWebUI.removeTeg('"+this.id+"');"]);
theContextMenu.add([theUILang.removeAllTegs, "theWebUI.removeAllTegs();"]);
theContextMenu.show(e.clientX,e.clientY);
}
@@ -2005,36 +2004,32 @@ var theWebUI =
loadLabels: function(c, s)
{
var p = $("#lbll");
- var temp = new Array();
- var keys = new Array();
- for(var lbl in c)
- keys.push(lbl);
- keys.sort();
-
- for(var i=0; i").
- attr("id","-_-_-" + lbl + "-_-_-").
- html(escapeHTML(lbl) + " (" + c[lbl] + lblSize + ")").
- mouseclick(theWebUI.labelContextMenu).addClass("cat") );
+ // use custom label
+ this.cLabels[lbl] = 1;
+ if(!$$(id))
+ {
+ p.append( this.createSelectableLabelElement(id, lbl, theWebUI.labelContextMenu));
+ }
}
+ this.labels[id] = { cnt: c[lbl], size: s[lbl] };
}
var actDeleted = false;
+ var pLabels = ['nlb'].concat(Object.keys(this.cLabels));
p.children().each(function(ndx,val)
{
var id = val.id;
- if(id && !$type(temp[id]))
- {
+ var lbl = (id&&id.substr(5, id.length - 10))||'nlb';
+ if (!pLabels.includes(lbl)) {
$(val).remove();
- delete theWebUI.labels[id];
- delete theWebUI.cLabels[id.substr(5, id.length - 10)];
if(theWebUI.actLbls["plabel_cont"] == id)
actDeleted = true;
}
@@ -2052,61 +2047,14 @@ var theWebUI =
*/
getLabels : function(id, torrent)
{
- if(!$type(this.labels[id]))
- this.labels[id] = "";
- var lbl = torrent.label;
- if(lbl == "")
- {
- lbl += "-_-_-nlb-_-_-";
- if(this.labels[id].indexOf("-_-_-nlb-_-_-") ==- 1)
- this.labels["-_-_-nlb-_-_-"]++;
- }
- else
- if(this.labels[id].indexOf("-_-_-nlb-_-_-") >- 1)
- this.labels["-_-_-nlb-_-_-"]--;
- lbl = "-_-_-" + lbl + "-_-_-";
- if(torrent.done < 1000)
- {
- lbl += "-_-_-dls-_-_-";
- if(this.labels[id].indexOf("-_-_-dls-_-_-") ==- 1)
- this.labels["-_-_-dls-_-_-"]++;
- if(this.labels[id].indexOf("-_-_-com-_-_-") >- 1)
- this.labels["-_-_-com-_-_-"]--;
- }
- else
- {
- lbl += "-_-_-com-_-_-";
- if(this.labels[id].indexOf("-_-_-com-_-_-") ==- 1)
- this.labels["-_-_-com-_-_-"]++;
- if(this.labels[id].indexOf("-_-_-dls-_-_-") >- 1)
- this.labels["-_-_-dls-_-_-"]--;
- }
- if((torrent.dl >= 1024) || (torrent.ul >= 1024))
- {
- lbl += "-_-_-act-_-_-";
- if(this.labels[id].indexOf("-_-_-act-_-_-") ==- 1)
- this.labels["-_-_-act-_-_-"]++;
- if(this.labels[id].indexOf("-_-_-iac-_-_-") >- 1)
- this.labels["-_-_-iac-_-_-"]--;
- }
- else
- {
- lbl += "-_-_-iac-_-_-";
- if(this.labels[id].indexOf("-_-_-iac-_-_-") ==- 1)
- this.labels["-_-_-iac-_-_-"]++;
- if(this.labels[id].indexOf("-_-_-act-_-_-") >- 1)
- this.labels["-_-_-act-_-_-"]--;
- }
- if(torrent.state & dStatus.error)
- {
- lbl += "-_-_-err-_-_-";
- if(this.labels[id].indexOf("-_-_-err-_-_-") ==- 1)
- this.labels["-_-_-err-_-_-"]++;
- }
- else
- if(this.labels[id].indexOf("-_-_-err-_-_-") >- 1)
- this.labels["-_-_-err-_-_-"]--;
- return(lbl);
+ this.stateLabels[id] = [
+ torrent.label.length ? '' : 'nlb',
+ torrent.done < 1000 ? 'dls' : 'com',
+ (torrent.dl >= 1024) || (torrent.ul >= 1024) ? 'act' : 'iac',
+ torrent.state & dStatus.error ? 'err' : '',
+ ].filter(lbl => lbl.length);
+ return((torrent.label.length ? '-_-_-' + torrent.label + '-_-_-' : '') +
+ this.stateLabels[id].map(function (lbl) { return('-_-_-' + lbl + '-_-_-'); }).join(''));
},
/**
@@ -2164,24 +2112,49 @@ var theWebUI =
}
},
+ createSelectableLabelElement: function(id, text, onClick) {
+ return( $("").attr("id",id)
+ .append($('').addClass('label-text').text(text))
+ .append($('').addClass('label-count').text(0))
+ .append($('').addClass('label-size'))
+ .attr("title",text+" (0)")
+ .mouseclick(onClick))
+ .addClass("cat");
+ },
+
+ updateLabel: function(label, count, size, showSize) {
+ var li = $(label);
+ var lblSize = theConverter.bytes(size, 2);
+ li.children('.label-count').text(count);
+ var txt = li.children('.label-text');
+ li.attr('title',
+ txt.contents().not(txt.children('script')).text() +
+ ' ('+ count + ( showSize ? ' ; '+ lblSize : '') +')');
+ var sizeSpan = li.children('.label-size');
+ sizeSpan.text(lblSize);
+ if (showSize)
+ {
+ sizeSpan.show();
+ } else {
+ sizeSpan.hide();
+ }
+ },
+
updateLabels: function(wasRemoved)
{
- $(".-_-_-all-_-_-c").text(Object.keys(this.torrents).length)
+ this.updateAllFilterLabel('pstate_cont', this.settings["webui.show_statelabelsize"]);
+ this.updateAllFilterLabel('plabel_cont', this.settings["webui.show_labelsize"]);
+ this.updateAllFilterLabel('flabel_cont', this.settings["webui.show_searchlabelsize"]);
for(var k in this.labels)
- if(k.substr(0, 5) == "-_-_-")
- $($$(k+"c")).text(this.labels[k]);
-
- for( var id in this.tegs )
- {
- var counter = $("#"+id+"-c");
- var teg = this.tegs[id];
- if(counter.text()!=teg.cnt)
- {
- counter.text(teg.cnt);
- $("#"+id).prop("title",teg.val+" ("+teg.cnt+")");
+ if(k.substr(0, 5) == "-_-_-") {
+ var lbl = k.substr(5, k.length - 10);
+ this.updateLabel(
+ $$(k),
+ this.labels[k].cnt,
+ this.labels[k].size,
+ this.staticLabels.includes(lbl) && lbl != 'nlb' ? this.settings["webui.show_statelabelsize"] : this.settings["webui.show_labelsize"]);
}
- }
},
resetLabels: function() {
diff --git a/lang/en.js b/lang/en.js
index a97fd74a1..51d022232 100644
--- a/lang/en.js
+++ b/lang/en.js
@@ -241,7 +241,9 @@ var theUILang =
scrapeUpdate : "Last Updated",
trkInterval : "Interval",
logAutoSwitch : "Autoswitch to 'Log' tab",
+ showStateLabelSize : "Show state size",
showLabelSize : "Show label size",
+ showSearchLabelSize : "Show search size",
phpParameterUnavailable : "PHP directive register_argc_argv is set to OFF. Change to ON, otherwise some plugins won't work correctly.",
addTorrentFailedURL : "Failed to add torrent. Can't retrieve URL.",
addTorrentFailedFile : "Failed to add torrent. The retrieved content is not a valid torrent file.",
diff --git a/plugins/httprpc/init.js b/plugins/httprpc/init.js
index 9d6af3f00..6a46df764 100644
--- a/plugins/httprpc/init.js
+++ b/plugins/httprpc/init.js
@@ -68,7 +68,7 @@ rTorrentStub.prototype.listResponse = function(data)
state|=dStatus.error;
torrent.state = state;
torrent.name = values[4];
- torrent.size = values[5];
+ torrent.size = iv(values[5]);
var get_completed_chunks = iv(values[6]);
var get_hashed_chunks = iv(values[24]);
var get_size_chunks = iv(values[7]);
@@ -85,20 +85,6 @@ rTorrentStub.prototype.listResponse = function(data)
torrent.label = decodeURIComponent(values[14]).trim();
} catch(e) { torrent.label = ''; }
- if(torrent.label.length>0)
- {
- if(!$type(ret.labels[torrent.label]))
- {
- ret.labels[torrent.label] = 1;
- ret.labels_size[torrent.label] = parseInt(torrent.size);
- }
- else
- {
- ret.labels[torrent.label]++;
- ret.labels_size[torrent.label] = parseInt(ret.labels_size[torrent.label]) + parseInt(torrent.size);
- }
- }
-
var get_peers_not_connected = iv(values[16]);
var get_peers_connected = iv(values[17]);
var get_peers_all = get_peers_not_connected+get_peers_connected;
diff --git a/plugins/rss/init.js b/plugins/rss/init.js
index ff9a55771..e35ed4274 100644
--- a/plugins/rss/init.js
+++ b/plugins/rss/init.js
@@ -636,21 +636,13 @@ theWebUI.updateRSSLabels = function(rssLabels,rssGroups)
for( var lbl in rssGroups )
{
- var li = null;
this.updateCounters( rssGroups[lbl], rssLabels );
- if(lbl in this.rssGroups)
+ if(!(lbl in this.rssGroups))
{
- li = $($$(lbl));
- li.html( escapeHTML(rssGroups[lbl].name)+' ('+rssGroups[lbl].cnt+')' );
+ ul.append(theWebUI.createSelectableLabelElement(lbl, rssGroups[lbl].name, this.rssLabelContextMenu));
}
- else
- {
- li = $("").attr("id",lbl).
- html( escapeHTML(rssGroups[lbl].name)+' ('+rssGroups[lbl].cnt+')').
- mouseclick( this.rssLabelContextMenu );
- ul.append(li);
- }
- li.attr("title",rssGroups[lbl].name+" ("+rssGroups[lbl].cnt+")");
+ theWebUI.updateLabel($$(lbl), rssGroups[lbl].cnt, 0, false);
+ var li = $($$(lbl));
if(lbl==this.actRSSLbl)
li[0].className = (rssGroups[lbl].enabled==1) ? "sel RSSGroup cat" : "sel disRSS cat";
else
@@ -674,26 +666,17 @@ theWebUI.updateRSSLabels = function(rssLabels,rssGroups)
keys.sort( function(a,b) { return((rssLabels[a].name>rssLabels[b].name) ? 1 : (rssLabels[a].name'+rssLabels[lbl].cnt+')' );
- }
- else
+ if(!(lbl in this.rssLabels))
{
- li = $("").attr("id",lbl).
- html( escapeHTML(rssLabels[lbl].name)+' ('+rssLabels[lbl].cnt+')').
- mouseclick( this.rssLabelContextMenu );
- ul.append(li);
+ ul.append(theWebUI.createSelectableLabelElement(lbl, rssLabels[lbl].name, this.rssLabelContextMenu));
}
- li.attr("title",rssLabels[lbl].name+" ("+rssLabels[lbl].cnt+")");
+ theWebUI.updateLabel($$(lbl), rssLabels[lbl].cnt, 0, false);
+ var li = $($$(lbl));
if(lbl==this.actRSSLbl)
li[0].className = (rssLabels[lbl].enabled==1) ? "sel RSS cat" : "sel disRSS cat";
else
@@ -1473,11 +1456,16 @@ plugin.onLangLoaded = function()
{
this.addButtonToToolbar("rss",theUILang.mnu_rss,"theWebUI.showRSS()","settings");
- plugin.addPaneToCategory("prss",theUILang.rssFeeds).
- append( $("").html('')).
- append( $("").html('') );
+ plugin.addPaneToCategory("prss",theUILang.rssFeeds)
+ .append( $("
")
+ .append(
+ theWebUI.createSelectableLabelElement(
+ '_rssAll_',
+ theUILang.allFeeds,
+ theWebUI.rssLabelContextMenu
+ ).addClass('RSS')
+ )).append( $("
").html('') );
$("#prss").append( $("
").attr("id", "rsstimer") );
- $("#_rssAll_").mouseclick( theWebUI.rssLabelContextMenu );
this.attachPageToOptions( $("
").attr("id","st_rss").html(
"