Performance improvements
* Pre-compute name, formatted sizes and speeds. * Handle name edge-cases such as no-path and no-uris better. * Unroll getCtx. * Improve performance of mergeMap. * Delay the search filter. As indicated by Chrome/Gecko profilers.
This commit is contained in:
parent
4ab27fb503
commit
38a413e95b
32
index.html
32
index.html
|
@ -264,7 +264,7 @@
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<div class="span4">
|
<div class="span4">
|
||||||
<label for="downloadFilter">Search</label>
|
<label for="downloadFilter">Search</label>
|
||||||
<input id="downloadFilter" type="text" ng-model="downloadFilter" class="input-large"/>
|
<input id="downloadFilter" type="text" ng-model="downloadFilter" ng-change="onDownloadFilter()" class="input-large"/>
|
||||||
<br>
|
<br>
|
||||||
<b>Found: {{totalDownloads}} / {{totalAria2Downloads()}} </b>
|
<b>Found: {{totalDownloads}} / {{totalAria2Downloads()}} </b>
|
||||||
</div>
|
</div>
|
||||||
|
@ -277,7 +277,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="download-name download-item" ng-click="download.collapsed = !download.collapsed">
|
<td class="download-name download-item" ng-click="download.collapsed = !download.collapsed">
|
||||||
{{getName(download)}}
|
{{download.name}}
|
||||||
</td>
|
</td>
|
||||||
<td class="download-controls download-item" rowspan="2">
|
<td class="download-controls download-item" rowspan="2">
|
||||||
<!-- {{{ download control buttons -->
|
<!-- {{{ download control buttons -->
|
||||||
|
@ -368,11 +368,11 @@
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="label label-active hidden-phone">
|
<li class="label label-active hidden-phone">
|
||||||
<span title="Download Size"><i class="icon-cloud-download"> </i> {{download.totalLength | blength}}</span>
|
<span title="Download Size"><i class="icon-cloud-download"> </i> {{download.fmtTotalLength}}</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="label label-active hidden-phone">
|
<li class="label label-active hidden-phone">
|
||||||
<span title="Downloaded"><i class="icon-download-alt"> </i> {{download.completedLength | blength}}</span>
|
<span title="Downloaded"><i class="icon-download-alt"> </i> {{download.fmtCompletedLength}}</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="label label-active hidden-phone hidden-tablet">
|
<li class="label label-active hidden-phone hidden-tablet">
|
||||||
|
@ -389,11 +389,11 @@
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="label label-info">
|
<li class="label label-info">
|
||||||
<span title="Download Size"><i class="icon-cloud-download"> </i> {{download.totalLength | blength}}</span>
|
<span title="Download Size"><i class="icon-cloud-download"> </i> {{download.fmtTotalLength}}</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="label label-info hidden-phone">
|
<li class="label label-info hidden-phone">
|
||||||
<span title="Downloaded"><i class="icon-download-alt"> </i> {{download.completedLength | blength}}</span>
|
<span title="Downloaded"><i class="icon-download-alt"> </i> {{download.fmtCompletedLength}}</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="label label-info hidden-phone">
|
<li class="label label-info hidden-phone">
|
||||||
|
@ -436,7 +436,7 @@
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="label label-success">
|
<li class="label label-success">
|
||||||
<span title="Download Size"><i class="icon-cloud-download"> </i> {{download.totalLength | blength}}</span>
|
<span title="Download Size"><i class="icon-cloud-download"> </i> {{download.fmtTotalLength}}</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<!-- }}} -->
|
<!-- }}} -->
|
||||||
|
@ -455,7 +455,7 @@
|
||||||
|
|
||||||
<li ng-show="hasStatus(download, 'removed')"
|
<li ng-show="hasStatus(download, 'removed')"
|
||||||
class="label label-warning">
|
class="label label-warning">
|
||||||
<span title="Download Size"><i class="icon-cloud-download"> </i> {{download.totalLength | blength}}</span>
|
<span title="Download Size"><i class="icon-cloud-download"> </i> {{download.fmtTotalLength}}</span>
|
||||||
</li>
|
</li>
|
||||||
<!-- }}} -->
|
<!-- }}} -->
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -471,7 +471,7 @@
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="label label-important">
|
<li class="label label-important">
|
||||||
<span title="Download Size"><i class="icon-cloud-download"> </i> {{download.totalLength | blength}}</span>
|
<span title="Download Size"><i class="icon-cloud-download"> </i> {{download.fmtTotalLength}}</span>
|
||||||
</li>
|
</li>
|
||||||
<!-- }}} -->
|
<!-- }}} -->
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -495,21 +495,21 @@
|
||||||
<ul class="stats download-item">
|
<ul class="stats download-item">
|
||||||
<li class="label" title="Download Path"><i class="icon-folder-open"> </i> <span class="download-dir">{{download.dir}}</span></li>
|
<li class="label" title="Download Path"><i class="icon-folder-open"> </i> <span class="download-dir">{{download.dir}}</span></li>
|
||||||
<li class="label" title="Estimated Time"><i class="icon-time"> </i> <span class="download-eta">{{getEta(download) | time}}</span></li>
|
<li class="label" title="Estimated Time"><i class="icon-time"> </i> <span class="download-eta">{{getEta(download) | time}}</span></li>
|
||||||
<li class="label" title="Download Size"><i class="icon-cloud-download"> </i> <span class="download-totalLength">{{download.totalLength | blength}}</span></li>
|
<li class="label" title="Download Size"><i class="icon-cloud-download"> </i> <span class="download-totalLength">{{download.fmtTotalLength}}</span></li>
|
||||||
<li class="label" title="Downloaded"><i class="icon-download-alt"> </i> <span class="download-completedLength">{{download.completedLength | blength}}</span></li>
|
<li class="label" title="Downloaded"><i class="icon-download-alt"> </i> <span class="download-completedLength">{{download.fmtCompletedLength}}</span></li>
|
||||||
<li class="label" title="Download Speed"><i class="icon-download"> </i> <span class="download-downloadSpeed">{{download.downloadSpeed | bspeed}}</span></li>
|
<li class="label" title="Download Speed"><i class="icon-download"> </i> <span class="download-downloadSpeed">{{download.fmtDownloadSpeed}}</span></li>
|
||||||
|
|
||||||
<li class="label" title="Upload Speed" ng-show="download.bittorrent"><i class="icon-upload"> </i> <span class="download-uploadSpeed">{{download.uploadSpeed | bspeed}}</span></li>
|
<li class="label" title="Upload Speed" ng-show="download.bittorrent"><i class="icon-upload"> </i> <span class="download-uploadSpeed">{{download.fmtUploadSpeed}}</span></li>
|
||||||
<li class="label" title="Uploaded" ng-show="download.bittorrent"><i class="icon-upload-alt"> </i> <span class="download-uploadLength">{{download.uploadLength | blength}}</span></li>
|
<li class="label" title="Uploaded" ng-show="download.bittorrent"><i class="icon-upload-alt"> </i> <span class="download-uploadLength">{{download.fmtUploadLength}}</span></li>
|
||||||
|
|
||||||
<li class="label" title="Connections"><i class="icon-link"> </i> <span class="download-connections">{{download.connections}}</span></li>
|
<li class="label" title="Connections"><i class="icon-link"> </i> <span class="download-connections">{{download.connections}}</span></li>
|
||||||
|
|
||||||
<li class="label" title="Download GID"><i class="icon-reorder"> </i> <span class="download-gid">{{download.gid}}</span></li>
|
<li class="label" title="Download GID"><i class="icon-reorder"> </i> <span class="download-gid">{{download.gid}}</span></li>
|
||||||
<li class="label" title="Number of Pieces"># of <i class="icon-puzzle-piece"> </i> <span class="download-numPieces">{{download.numPieces}}</span></li>
|
<li class="label" title="Number of Pieces"># of <i class="icon-puzzle-piece"> </i> <span class="download-numPieces">{{download.numPieces}}</span></li>
|
||||||
<li class="label" title="Piece Length"><i class="icon-puzzle-piece"></i> Length <span class="download-pieceLength">{{download.pieceLength | blength}}</span></li>
|
<li class="label" title="Piece Length"><i class="icon-puzzle-piece"></i> Length <span class="download-pieceLength">{{download.fmtPieceLength}}</span></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="download-files hidden-phone download-item">
|
<ul class="download-files hidden-phone download-item">
|
||||||
<li class="label" ng-repeat="file in download.files">{{file.relpath}} ({{file.length | blength}})</li>
|
<li class="label" ng-repeat="file in download.files">{{file.relpath}} ({{file.fmtLength}})</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div ng-show="hasStatus(download, 'active')" class="download-item">
|
<div ng-show="hasStatus(download, 'active')" class="download-item">
|
||||||
<div class="download-graph" dspeed="download.downloadSpeed" uspeed="download.uploadSpeed" dgraph draw="!download.collapsed"></div>
|
<div class="download-graph" dspeed="download.downloadSpeed" uspeed="download.uploadSpeed" dgraph draw="!download.collapsed"></div>
|
||||||
|
|
|
@ -106,10 +106,26 @@ function(
|
||||||
|
|
||||||
// download search filter
|
// download search filter
|
||||||
scope.downloadFilter = "";
|
scope.downloadFilter = "";
|
||||||
|
scope.downloadFilterCommitted = "";
|
||||||
|
|
||||||
|
scope.onDownloadFilter = function() {
|
||||||
|
if (scope.downloadFilterTimer) {
|
||||||
|
clearTimeout(scope.downloadFilterTimer);
|
||||||
|
}
|
||||||
|
scope.downloadFilterTimer = setTimeout(function() {
|
||||||
|
delete scope.downloadFilterTimer;
|
||||||
|
if (scope.downloadFilterCommitted !== scope.downloadFilter) {
|
||||||
|
scope.downloadFilterCommitted = scope.downloadFilter;
|
||||||
|
scope.$digest();
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
};
|
||||||
|
|
||||||
scope.filterDownloads = function(downloads) {
|
scope.filterDownloads = function(downloads) {
|
||||||
var filter = scope.downloadFilter;
|
if (!scope.downloadFilterCommitted) {
|
||||||
if (!filter.length) return downloads;
|
return downloads;
|
||||||
|
}
|
||||||
|
var filter = scope.downloadFilterCommitted;
|
||||||
return _.filter(downloads, function(d) {
|
return _.filter(downloads, function(d) {
|
||||||
if (!d.files.length) return true;
|
if (!d.files.length) return true;
|
||||||
|
|
||||||
|
@ -187,27 +203,79 @@ function(
|
||||||
// convert the donwload form aria2 to once used by the view,
|
// convert the donwload form aria2 to once used by the view,
|
||||||
// minor additions of some fields and checks
|
// minor additions of some fields and checks
|
||||||
scope.getCtx = function(d, ctx) {
|
scope.getCtx = function(d, ctx) {
|
||||||
ctx = ctx || {};
|
if (!ctx) {
|
||||||
|
ctx = {
|
||||||
|
dir: d.dir,
|
||||||
|
status: d.status,
|
||||||
|
gid: d.gid,
|
||||||
|
numPieces: d.numPieces,
|
||||||
|
connections: d.connections,
|
||||||
|
bitfield: d.bitfield,
|
||||||
|
totalLength: d.totalLength,
|
||||||
|
fmtTotalLength: utils.fmtsize(d.totalLength),
|
||||||
|
completedLength: d.completedLength,
|
||||||
|
fmtCompletedLength: utils.fmtsize(d.completedLength),
|
||||||
|
uploadLength: d.uploadLength,
|
||||||
|
fmtUploadLength: utils.fmtsize(d.uploadLength),
|
||||||
|
pieceLength: d.pieceLength,
|
||||||
|
fmtPieceLength: utils.fmtsize(d.pieceLength),
|
||||||
|
downloadSpeed: d.downloadSpeed,
|
||||||
|
fmtDownloadSpeed: utils.fmtspeed(d.downloadSpeed),
|
||||||
|
uploadSpeed: d.uploadSpeed,
|
||||||
|
fmtUploadSpeed: utils.fmtspeed(d.uploadSpeed),
|
||||||
|
files: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ctx.dir = d.dir;
|
||||||
|
ctx.status = d.status;
|
||||||
|
ctx.gid = d.gid;
|
||||||
|
ctx.numPieces = d.numPieces;
|
||||||
|
ctx.connections = d.connections;
|
||||||
|
ctx.bitfield = d.bitfield;
|
||||||
|
if (ctx.totalLength !== d.totalLength) {
|
||||||
|
ctx.totalLength = d.totalLength;
|
||||||
|
ctx.fmtTotalLength = utils.fmtsize(d.totalLength);
|
||||||
|
}
|
||||||
|
if (ctx.completedLength !== d.completedLength) {
|
||||||
|
ctx.completedLength = d.completedLength;
|
||||||
|
ctx.fmtCompletedLength = utils.fmtsize(d.completedLength);
|
||||||
|
}
|
||||||
|
if (ctx.uploadLength !== d.uploadength) {
|
||||||
|
ctx.uploadLength = d.uploadlength;
|
||||||
|
ctx.fmtUploadLength = utils.fmtsize(d.uploadLength);
|
||||||
|
}
|
||||||
|
if (ctx.pieceLength !== d.pieceLength) {
|
||||||
|
ctx.pieceLength = d.pieceLength;
|
||||||
|
ctx.fmtPieceLength = utils.fmtsize(d.pieceLength);
|
||||||
|
}
|
||||||
|
if (ctx.downloadSpeed !== d.downloadSpeed) {
|
||||||
|
ctx.downloadSpeed = d.downloadSpeed;
|
||||||
|
ctx.fmtDownloadSpeed = utils.fmtspeed(d.downloadSpeed);
|
||||||
|
}
|
||||||
|
if (ctx.uploadSpeed !== d.uploadSpeed) {
|
||||||
|
ctx.uploadSpeed = d.uploadSpeed;
|
||||||
|
ctx.fmtUploadSpeed = utils.fmtspeed(d.uploadSpeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_.each([
|
var dlName;
|
||||||
'totalLength', 'completedLength', 'uploadLength', 'dir',
|
var files = d.files;
|
||||||
'pieceLength', 'downloadSpeed', 'uploadSpeed', 'status',
|
|
||||||
'gid', 'numPieces', 'connections', 'bitfield'
|
|
||||||
], function(e) {
|
|
||||||
ctx[e] = d[e];
|
|
||||||
});
|
|
||||||
|
|
||||||
var files = d["files"];
|
|
||||||
if (files) {
|
if (files) {
|
||||||
var cfiles = ctx["files"] || (ctx["files"] = []);
|
dlName = files[0].path || d.files[0].uris[0].uri;
|
||||||
|
var cfiles = ctx.files;
|
||||||
for (var i = 0; i < files.length; ++i) {
|
for (var i = 0; i < files.length; ++i) {
|
||||||
var cfile = cfiles[i] || (cfiles[i] = {});
|
var cfile = cfiles[i] || (cfiles[i] = {});
|
||||||
var file = files[i];
|
var file = files[i];
|
||||||
if (file.path !== cfile.path) {
|
if (file.path !== cfile.path) {
|
||||||
cfile.path = file.path;
|
cfile.path = file.path;
|
||||||
cfile.length = file.length;
|
cfile.length = file.length;
|
||||||
|
cfile.fmtLength = utils.fmtsize(file.length);
|
||||||
cfile.relpath = file.path.replace(re_slashes, slash);
|
cfile.relpath = file.path.replace(re_slashes, slash);
|
||||||
if (!cfile.relpath.startsWith("[")) { // METADATA
|
if (!cfile.relpath) {
|
||||||
|
cfile.relpath = (file.uris && file.uris[0] && file.uris[0].uri) || "Unknown";
|
||||||
|
}
|
||||||
|
else if (!cfile.relpath.startsWith("[")) { // METADATA
|
||||||
cfile.relpath = cfile.relpath.substr(ctx.dir.length + 1);
|
cfile.relpath = cfile.relpath.substr(ctx.dir.length + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,20 +283,24 @@ function(
|
||||||
cfiles.length = files.length;
|
cfiles.length = files.length;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
delete ctx["files"];
|
delete ctx.files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var btName;
|
||||||
if (d.bittorrent) {
|
if (d.bittorrent) {
|
||||||
ctx.bittorrentName = d.bittorrent.info && d.bittorrent.info.name;
|
btName = d.bittorrent.info && d.bittorrent.info.name;
|
||||||
ctx.bittorrent = true;
|
ctx.bittorrent = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
delete ctx.bittorrentName;
|
delete ctx.bittorrent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.name = btName || utils.getFileName(dlName) || dlName || "Unknown";
|
||||||
|
|
||||||
// collapse the download details initially
|
// collapse the download details initially
|
||||||
if (ctx.collapsed === undefined)
|
if (ctx.collapsed === undefined) {
|
||||||
ctx.collapsed = true;
|
ctx.collapsed = true;
|
||||||
|
}
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
};
|
};
|
||||||
|
@ -284,17 +356,6 @@ function(
|
||||||
return percentage;
|
return percentage;
|
||||||
};
|
};
|
||||||
|
|
||||||
// gets a pretty name for the download
|
|
||||||
scope.getName = function(d) {
|
|
||||||
if (d.bittorrentName) {
|
|
||||||
return d.bittorrentName;
|
|
||||||
}
|
|
||||||
|
|
||||||
return utils.getFileName(
|
|
||||||
d.files[0].path || d.files[0].uris[0].uri
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// gets the type for the download as classified by the aria2 rpc calls
|
// gets the type for the download as classified by the aria2 rpc calls
|
||||||
scope.getType = function(d) {
|
scope.getType = function(d) {
|
||||||
var type = d.status;
|
var type = d.status;
|
||||||
|
@ -320,7 +381,7 @@ function(
|
||||||
settings[i].val = vals[i] || settings[i].val;
|
settings[i].val = vals[i] || settings[i].val;
|
||||||
}
|
}
|
||||||
|
|
||||||
modals.invoke('settings', settings, scope.getName(d) + ' settings', function(settings) {
|
modals.invoke('settings', settings, scope.name + ' settings', function(settings) {
|
||||||
var sets = {};
|
var sets = {};
|
||||||
for (var i in settings) { sets[i] = settings[i].val };
|
for (var i in settings) { sets[i] = settings[i].val };
|
||||||
|
|
||||||
|
|
|
@ -1,47 +1,25 @@
|
||||||
(function() {
|
angular.module('webui.filters.bytes', ["webui.services.utils"])
|
||||||
function fmtlen(len) {
|
.filter('blength', ['$filter', "$utils", function(filter, utils) {
|
||||||
len = +len; // coerce to number
|
return utils.fmtsize;
|
||||||
if (len <= 1024) {
|
}])
|
||||||
return len.toFixed(0) + " B";
|
.filter('bspeed', ['$filter', "$utils", function(filter, utils) {
|
||||||
}
|
return utils.fmtspeed;
|
||||||
len /= 1024;
|
}])
|
||||||
if (len <= 1024) {
|
.filter('time', function() {
|
||||||
return len.toFixed(1) + " KB"
|
function pad(f) {
|
||||||
}
|
return ("0" + f).substr(-2);
|
||||||
len /= 1024;
|
|
||||||
if (len <= 1024) {
|
|
||||||
return len.toFixed(2) + " MB";
|
|
||||||
}
|
|
||||||
len /= 1024;
|
|
||||||
return len.toFixed(3) + " GB";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
angular .module('webui.filters.bytes', [])
|
return function(time) {
|
||||||
.filter('blength', ['$filter', function(filter) {
|
time = parseInt(time, 10);
|
||||||
return fmtlen;
|
if (!time || !isFinite(time)) return "∞";
|
||||||
}])
|
var secs = time % 60;
|
||||||
.filter('bspeed', ['$filter', function(filter) {
|
if (time < 60) return secs + "s";
|
||||||
return function(speed) {
|
var mins = Math.floor((time % 3600) / 60)
|
||||||
return fmtlen(speed) + "/s";
|
if (time < 3600) return pad(mins) + ":" + pad(secs);
|
||||||
};
|
var hrs = Math.floor((time % 86400) / 3600);
|
||||||
}])
|
if (time < 86400) return pad(hrs) + ":" + pad(mins) + ":" + pad(secs);
|
||||||
.filter('time', function() {
|
var days = Math.floor(time / 86400);
|
||||||
function pad(f) {
|
return days + "::" + pad(hrs) + ":" + pad(mins) + ":" + pad(secs);
|
||||||
return ("0" + f).substr(-2);
|
};
|
||||||
}
|
});
|
||||||
|
|
||||||
return function(time) {
|
|
||||||
time = parseInt(time, 10);
|
|
||||||
if (!time || !isFinite(time)) return "∞";
|
|
||||||
var secs = time % 60;
|
|
||||||
if (time < 60) return secs + "s";
|
|
||||||
var mins = Math.floor((time % 3600) / 60)
|
|
||||||
if (time < 3600) return pad(mins) + ":" + pad(secs);
|
|
||||||
var hrs = Math.floor((time % 86400) / 3600);
|
|
||||||
if (time < 86400) return pad(hrs) + ":" + pad(mins) + ":" + pad(secs);
|
|
||||||
var days = Math.floor(time / 86400);
|
|
||||||
return days + "::" + pad(hrs) + ":" + pad(mins) + ":" + pad(secs);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,28 @@ angular.module('webui.services.utils', [])
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
return {
|
var utils = {
|
||||||
|
|
||||||
|
fmtsize: function(len) {
|
||||||
|
len = +len; // coerce to number
|
||||||
|
if (len <= 1024) {
|
||||||
|
return len.toFixed(0) + " B";
|
||||||
|
}
|
||||||
|
len /= 1024;
|
||||||
|
if (len <= 1024) {
|
||||||
|
return len.toFixed(1) + " KB"
|
||||||
|
}
|
||||||
|
len /= 1024;
|
||||||
|
if (len <= 1024) {
|
||||||
|
return len.toFixed(2) + " MB";
|
||||||
|
}
|
||||||
|
len /= 1024;
|
||||||
|
return len.toFixed(3) + " GB";
|
||||||
|
},
|
||||||
|
|
||||||
|
fmtspeed: function(speed) {
|
||||||
|
return utils.fmtsize(speed) + "/s";
|
||||||
|
},
|
||||||
// saves the key value pair in cookies
|
// saves the key value pair in cookies
|
||||||
setCookie: function(key, value) {
|
setCookie: function(key, value) {
|
||||||
var exdate = new Date();
|
var exdate = new Date();
|
||||||
|
@ -70,31 +91,29 @@ angular.module('webui.services.utils', [])
|
||||||
};
|
};
|
||||||
})(),
|
})(),
|
||||||
randStr: function() {
|
randStr: function() {
|
||||||
return this.uuid();
|
return utils.uuid();
|
||||||
},
|
},
|
||||||
|
|
||||||
// maps the array in place to the destination
|
// maps the array in place to the destination
|
||||||
// arr, dest (optional): array
|
// arr, dest (optional): array
|
||||||
// func: a merge mapping func, see ctrls/download.js
|
// func: a merge mapping func, see ctrls/download.js
|
||||||
mergeMap: function(arr, dest, func) {
|
mergeMap: function(arr, dest, func) {
|
||||||
if (!dest) dest = [];
|
if (!dest) {
|
||||||
|
dest = [];
|
||||||
for (var i = 0; i < dest.length; i++) {
|
}
|
||||||
if (i >= arr.length) {
|
|
||||||
// remove the deleted downloads
|
|
||||||
dest.splice(i, dest.length - arr.length);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!dest[i]) dest[i] = {};
|
|
||||||
|
|
||||||
|
for (var i = 0, e = Math.min(arr.length, dest.length); i < e; ++i) {
|
||||||
func(arr[i], dest[i]);
|
func(arr[i], dest[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert newly created downloads
|
// Insert newly created downloads
|
||||||
while (i < arr.length) {
|
while (i < arr.length) {
|
||||||
dest.push(func(arr[i++]));
|
dest.push(func(arr[i++]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Truncate if necessary.
|
||||||
|
dest.length = arr.length;
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
},
|
},
|
||||||
// get info title from global statistics
|
// get info title from global statistics
|
||||||
|
@ -144,4 +163,5 @@ angular.module('webui.services.utils', [])
|
||||||
return chunks;
|
return chunks;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
return utils;
|
||||||
}]);
|
}]);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user