refactoed rpc and templates with ui hints for download status

This commit is contained in:
hamza zia 2013-01-17 11:51:03 +05:00
parent 50218debae
commit e64b3fbd66
9 changed files with 241 additions and 244 deletions

View File

@ -136,73 +136,73 @@
<div id="active_downloads">
<table class="active-download" ng-repeat="download in getDownloads()">
<tbody>
<tr>
<td data-toggle="collapse" data-target=".download-detail .collapse" class="download-overview">
<b class="download-name">{{name}}</b>
<tbody>
<tr>
<td data-toggle="collapse" data-target=".download-detail .collapse" class="download-overview">
<b class="download-name">{{name}}</b>
<ul class="stats hidden-phone pull-right">
<li class="label label-success">Time left: <span class="download-eta">{{eta}}</span></li>
<li class="label label-success">Download Speed: <span class="download-down_speed">{{down_speed}}</span></li>
<li class="label label-success">Progress: <span class="download-down_speed">{{percentage}}%</span></li>
</ul>
<div class="progress full-progress progress-striped active" style="width: 100%; margin: 0; padding: 0;">
<div class="bar" style="width: 90%;"></div>
</div>
</td>
<td class="download-controls">
<div class="btn-group">
<button class="btn btn-mini download_pause"><i class="icon-pause"></i></button>
<button class="btn dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<ul class="stats hidden-phone pull-right">
<li class="label label-success">Time left: <span class="download-eta">{{eta}}</span></li>
<li class="label label-success">Download Speed: <span class="download-down_speed">{{down_speed}}</span></li>
<li class="label label-success">Progress: <span class="download-down_speed">{{percentage}}%</span></li>
</ul>
<div class="progress full-progress progress-striped active" style="width: 100%; margin: 0; padding: 0;">
<div class="bar" style="width: 90%;"></div>
</div>
</td>
<td class="download-controls">
<div class="btn-group">
<button class="btn btn-mini download_pause"><i class="icon-pause"></i></button>
<button class="btn dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a><i class="icon-cog"></i> Settings</a></li>
<li><a><i class="icon-list-alt"></i> Peers</a></li>
<li><a data-toggle="collapse" data-target=".download-detail .collapse"><i class="icon-info-sign"></i> More Info</a></li>
<li><a href="#"><i class="icon-remove"></i> Remove</a></li>
</ul>
</div>
</td>
</tr>
<tr data-toggle="collapse" data-target=".download-detail .collapse" class="download-detail">
<td colspan="2">
<div class="collapse more_info">
<canvas class="progress chunk-canvas" width="1400" style="width: 100%;"></canvas>
<ul class="stats">
<li class="label">Status: <span class="download-status">{{status}}</span></li>
<li class="label">GID: <span class="download-gid">{{gid}}</span></li>
<li class="label">Dir: <span class="download-dir">{{dir}}</span></li>
<li class="label">Size: <span class="download-size">{{size}}</span></li>
<li class="label">Downloaded: <span class="download-downloaded">{{downloaded}}</span></li>
<li class="label">Num of Pieces: <span class="download-numPieces">{{numPieces}}</span></li>
<li class="label">Piece Length: <span class="download-pieceLength">{{pieceLength}}</span></li>
<li class="label">ETA: <span class="download-eta">{{eta}}</span></li>
<li class="label">Down Speed: <span class="download-down_speed">{{down_speed}}</span></li>
<li class="label">Upload Speed: <span class="download-upload_speed">{{upload_speed}}</span></li>
<li class="label">Upload Length: <span class="download-uploadLength">{{uploadLength}}</span></li>
<li class="label">Connections: <span class="download-connections">{{connections}}</span></li>
</ul>
<li><a><i class="icon-cog"></i> Settings</a></li>
<li><a><i class="icon-list-alt"></i> Peers</a></li>
<li><a data-toggle="collapse" data-target=".download-detail .collapse"><i class="icon-info-sign"></i> More Info</a></li>
<li><a href="#"><i class="icon-remove"></i> Remove</a></li>
</ul>
</div>
</td>
</tr>
<tr data-toggle="collapse" data-target=".download-detail .collapse" class="download-detail">
<td colspan="2">
<div class="collapse more_info">
<canvas class="progress chunk-canvas" width="1400" style="width: 100%;"></canvas>
<ul class="stats">
<li class="label">Status: <span class="download-status">{{status}}</span></li>
<li class="label">GID: <span class="download-gid">{{gid}}</span></li>
<li class="label">Dir: <span class="download-dir">{{dir}}</span></li>
<li class="label">Size: <span class="download-size">{{size}}</span></li>
<li class="label">Downloaded: <span class="download-downloaded">{{downloaded}}</span></li>
<li class="label">Num of Pieces: <span class="download-numPieces">{{numPieces}}</span></li>
<li class="label">Piece Length: <span class="download-pieceLength">{{pieceLength}}</span></li>
<li class="label">ETA: <span class="download-eta">{{eta}}</span></li>
<li class="label">Down Speed: <span class="download-down_speed">{{down_speed}}</span></li>
<li class="label">Upload Speed: <span class="download-upload_speed">{{upload_speed}}</span></li>
<li class="label">Upload Length: <span class="download-uploadLength">{{uploadLength}}</span></li>
<li class="label">Connections: <span class="download-connections">{{connections}}</span></li>
</ul>
<h4 class="hidden-phone">Download Files</h4>
<ul class="download-files hidden-phone">
<li class="label">{{path}} ({{size}})</li>
</ul>
<h4 class="hidden-phone">Download Files</h4>
<ul class="download-files hidden-phone">
<li class="label">{{path}} ({{size}})</li>
</ul>
<div>
<div class="download-graph"></div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
<div>
<div class="download-graph"></div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div id="waiting_downloads"></div>
<div id="waiting_downloads"></div>
<div id="stopped_downloads"></div>
<div id="stopped_downloads"></div>
</div>

View File

@ -73,35 +73,88 @@
</style>
<!-- }}} -->
<!--{{{ active downloads template -->
<script type="text/mustache" id="download_active_template">
<table class="active-download" data-gid="{{gid}}" data-settingsName={{sett_name}}>
<!--- {{{ download template -->
<script type="text/mustache" id="download_template">
<table class="{{type}}-download" data-gid="{{gid}}" data-settingsName={{sett_name}}>
<tbody>
<tr>
<td data-toggle="collapse" data-target="[data-gid={{gid}}] .download-detail .collapse" class="download-overview">
<b class="download-name">{{name}}</b>
<ul class="stats hidden-phone pull-right">
{{#booleans.can_pause}}
<li class="label label-success">Time left: <span class="download-eta">{{eta}}</span></li>
<li class="label label-success">Download Speed: <span class="download-down_speed">{{down_speed}}</span></li>
<li class="label label-success">Progress: <span class="download-down_speed">{{percentage}}%</span></li>
<li class="label label-success">Progress: <span class="download-percentage">{{percentage}}</span>%</li>
{{/booleans.can_pause}}
{{#booleans.can_play}}
<li class="label label-info">Size: <span class="download-size">{{size}}</span></li>
<li class="label label-info">Downloaded: <span class="download-downloaded">{{downloaded}}</span></li>
<li class="label label-info">Path: <span class="download-dir">{{dir}}</span></li>
{{/booleans.can_play}}
{{#booleans.is_complete}}
<li class="label">Path: <span class="download-dir">{{dir}}</span></li>
<li class="label">Size: <span class="download-size">{{size}}</span></li>
{{/booleans.is_complete}}
{{#booleans.is_removed}}
<li class="label label-warning">Path: <span class="download-dir">{{dir}}</span></li>
<li class="label label-warning">Size: <span class="download-size">{{size}}</span></li>
{{/booleans.is_removed}}
{{#booleans.is_error}}
<li class="label label-important">Path: <span class="download-dir">{{dir}}</span></li>
<li class="label label-important">Size: <span class="download-size">{{size}}</span></li>
{{/booleans.is_error}}
</ul>
<div class="progress full-progress progress-striped active" style="width: 100%; margin: 0; padding: 0;">
{{#booleans.can_pause}}
<div class="progress progress-striped active" style="width: 100%; margin: 0; padding: 0;">
<div class="bar" style="width: {{percentage}}%;"></div>
</div>
{{/booleans.can_pause}}
{{#booleans.can_play}}
<div class="progress progress-info progress-striped" style="width: 100%; margin: 0; padding: 0;">
<div class="bar" style="width: {{percentage}}%;"></div>
</div>
{{/booleans.can_play}}
{{#booleans.is_error}}
<div class="progress progress-danger progress-striped" style="width: 100%; margin: 0; padding: 0;">
<div class="bar" style="width: {{percentage}}%;"></div>
</div>
{{/booleans.is_error}}
{{#booleans.is_removed}}
<div class="progress progress-warning progress-striped" style="width: 100%; margin: 0; padding: 0;">
<div class="bar" style="width: {{percentage}}%;"></div>
</div>
{{/booleans.is_removed}}
{{#booleans.is_complete}}
<div class="progress progress-success progress-striped" style="width: 100%; margin: 0; padding: 0;">
<div class="bar" style="width: {{percentage}}%;"></div>
</div>
{{/booleans.is_complete}}
</td>
<td class="download-controls">
<div class="btn-group">
{{#booleans.can_pause}}
<button class="btn btn-mini download_pause"><i class="icon-pause"></i></button>
{{/booleans.can_pause}}
{{#booleans.can_play}}
<button class="btn btn-mini download_play"><i class="icon-play"></i></button>
{{/booleans.can_play}}
{{#booleans.can_restart}}
<button class="btn btn-mini download_restart"><i class="icon-repeat"></i></button>
{{/booleans.can_restart}}
<button class="btn dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
{{#booleans.has_settings}}
<li><a href="#" class="download_settings"><i class="icon-cog"></i> Settings</a></li>
{{#bittorrent}}
<li><a href="#" class="torrent_info"><i class="icon-list-alt"></i> Peers</a></li>
{{/bittorrent}}
{{/booleans.has_settings}}
<li><a href="#" data-toggle="collapse" data-target="[data-gid={{gid}}] .download-detail .collapse"><i class="icon-info-sign"></i> More Info</a></li>
<li><a href="#" class="download_remove"><i class="icon-remove"></i> Remove</a></li>
</ul>
@ -143,125 +196,7 @@
</tbody>
</table>
</script>
<!-- active downloads template end }}}-->
<!--{{{ waiting downloads template-->
<script type="text/mustache" id="download_waiting_template">
<table class="waiting-download" data-gid="{{gid}}" data-settingsName={{sett_name}}>
<tbody>
<tr>
<td data-toggle="collapse" data-target="[data-gid={{gid}}] .download-detail .collapse" class="download-overview">
<b class="download-name">{{name}}</b>
<ul class="stats hidden-phone pull-right">
<li class="label label-success">Size: <span class="download-size">{{size}}</span></li>
<li class="label label-success">Downloaded: <span class="download-downloaded">{{downloaded}}</span></li>
<li class="label label-success">Path: <span class="download-dir">{{dir}}</span></li>
</ul>
<div class="progress full-progress progress-striped active" style="width: 100%; margin: 0; padding: 0;">
<div class="bar" style="width: {{percentage}}%;"></div>
</div>
</td>
<td class="download-controls">
<div class="btn-group">
<button class="btn btn-mini download_play"><i class="icon-play"></i></button>
<button class="btn dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="#" class="download_settings"><i class="icon-cog"></i> Settings</a></li>
<li><a href="#" data-toggle="collapse" data-target="[data-gid={{gid}}] .download-detail .collapse"><i class="icon-info-sign"></i> More Info</a></li>
<li><a href="#" class="download_remove"><i class="icon-remove"></i> Remove</a></li>
</ul>
</div>
</td>
</tr>
<tr data-toggle="collapse" data-target="[data-gid={{gid}}] .download-detail .collapse" class="download-detail">
<td colspan="2">
<div class="collapse more_info">
<ul class="stats">
<li class="label">Status: <span class="download-status">{{status}}</span></li>
<li class="label">GID: <span class="download-gid">{{gid}}</span></li>
<li class="label">Dir: <span class="download-dir">{{dir}}</span></li>
<li class="label">Size: <span class="download-size">{{size}}</span></li>
<li class="label">Downloaded: <span class="download-downloaded">{{downloaded}}</span></li>
<li class="label">Num of Pieces: <span class="download-numPieces">{{numPieces}}</span></li>
<li class="label">Piece Length: <span class="download-pieceLength">{{pieceLength}}</span></li>
<li class="label">ETA: <span class="download-eta">{{eta}}</span></li>
<li class="label">Down Speed: <span class="download-down_speed">{{down_speed}}</span></li>
<li class="label">Upload Speed: <span class="download-upload_speed">{{upload_speed}}</span></li>
<li class="label">Upload Length: <span class="download-uploadLength">{{uploadLength}}</span></li>
<li class="label">Connections: <span class="download-connections">{{connections}}</span></li>
</ul>
<h4 class="hidden-phone">Download Files</h4>
<ul class="download-files hidden-phone">
{{#files}}
<li class="label">{{path}} ({{size}})</li>
{{/files}}
</ul>
</div>
</td>
</tr>
</tbody>
</table>
</script>
<!-- waiting downloads template end }}}-->
<!--{{{ stopped downloads template-->
<script type="text/mustache" id="download_stopped_template">
<table class="stopped-download" data-gid="{{gid}}">
<tbody>
<tr>
<td data-toggle="collapse" data-target="[data-gid={{gid}}] .download-detail .collapse" class="download-overview">
<b class="download-name">{{name}}</b>
<ul class="stats hidden-phone pull-right">
<li class="label label-success">Path: <span class="download-dir">{{dir}}</span></li>
</ul>
<div class="progress full-progress progress-striped active" style="width: 100%; margin: 0; padding: 0;">
<div class="bar" style="width: {{percentage}}%;"></div>
</div>
</td>
<td class="download-controls">
<div class="btn-group">
<button class="btn btn-mini download_restart"><i class="icon-repeat"></i></button>
<button class="btn dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="#" data-toggle="collapse" data-target="[data-gid={{gid}}] .download-detail .collapse"><i class="icon-info-sign"></i> More Info</a></li>
<li><a href="#" class="download_remove"><i class="icon-remove"></i> Remove</a></li>
</ul>
</div>
</td>
</tr>
<tr data-toggle="collapse" data-target="[data-gid={{gid}}] .download-detail .collapse" class="download-detail">
<td colspan="2">
<div class="collapse more_info">
<ul class="stats">
<li class="label">Status: <span class="download-status">{{status}}</span></li>
<li class="label">GID: <span class="download-gid">{{gid}}</span></li>
<li class="label">Dir: <span class="download-dir">{{dir}}</span></li>
<li class="label">Size: <span class="download-size">{{size}}</span></li>
<li class="label">Downloaded: <span class="download-downloaded">{{downloaded}}</span></li>
<li class="label">Num of Pieces: <span class="download-numPieces">{{numPieces}}</span></li>
<li class="label">Piece Length: <span class="download-pieceLength">{{pieceLength}}</span></li>
<li class="label">ETA: <span class="download-eta">{{eta}}</span></li>
<li class="label">Down Speed: <span class="download-down_speed">{{down_speed}}</span></li>
<li class="label">Upload Speed: <span class="download-upload_speed">{{upload_speed}}</span></li>
<li class="label">Upload Length: <span class="download-uploadLength">{{uploadLength}}</span></li>
<li class="label">Connections: <span class="download-connections">{{connections}}</span></li>
</ul>
</div>
</td>
</tr>
</tbody>
</table>
</script>
<!-- stopped downloads template end }}}-->
<!-- }}} -->
<!--{{{ start global settings item template -->
<script type="text/mustache" id="global_general_settings_template">
@ -445,7 +380,6 @@
<a class="brand" href="#">aria2 Web-Client</a>
<div class="nav-collapse">
<ul class="nav">
<li class="active"><a href="#">All Downloads</a></li>
<li class="dropdown" id="add_download">
<a class="dropdown-toggle" data-toggle="dropdown" href="#add_download">
Add <b class="caret"></b>

View File

@ -1,40 +1,36 @@
app.controller('DownloadCtrl', [ '$scope', '$rpc',
function(scope, rpc) {
rpc.configure({
host: 'localhost',
port: 6800
});
app.controller('DownloadCtrl', [ '$scope', '$rpc', '$utils',
function(scope, rpc, utils) {
scope.active = scope.waiting = scope.stopped = [];
rpc.subscribe('tellActive', [], function(data) {
console.log('got active data');
scope.$apply(function() {
scope.active = data[0];
scope.active = data[0].map(scope.normalize);
});
});
rpc.subscribe('tellWaiting', [0, 100], function(data) {
scope.$apply(function() {
scope.waiting = data[0];
scope.waiting = data[0].map(scope.normalize);
});
});
rpc.subscribe('tellStopped', [0, 100], function(data) {
scope.$apply(function() {
scope.stopped = data[0];
scope.stopped = data[0].map(scope.normalize);
});
});
scope.getDownloads = function() {
var rets = scope.active
.concat(scope.waiting).concat(scope.stopped);
.concat(scope.waiting).concat(scope.stopped)
return rets;
}
scope.normalize = function(d) {
return "hello";
return d;
}
}]);

View File

@ -371,10 +371,14 @@ function getTemplateCtx(data) {
var chunks = percentage !== 100 && data.bitfield ? getChunksFromHex(data.bitfield, data.numPieces) : [];
var eta = changeTime((data.totalLength-data.completedLength)/data.downloadSpeed);
var type = data.status;
if (type == "paused") type = "waiting";
if (type == "error" || type == "removed" || type == "complete") type = "stopped";
return {
name: name,
sett_name: name.substr(0,name.lastIndexOf('.')) || name,
status: data.status,
type: type,
percentage:percentage,
gid: data.gid,
size: changeLength(data.totalLength, "B"),
@ -389,7 +393,13 @@ function getTemplateCtx(data) {
connections: data.connections,
upload_speed: changeLength(data.uploadSpeed, "B/s"),
booleans: {
is_error: data.status === "error"
is_error: data.status === "error",
is_complete: data.status === "complete",
is_removed: data.status === "removed",
has_settings: ["active", "waiting", "paused"].indexOf(data.status) != -1,
can_pause: type == "active",
can_play: type == "waiting",
can_restart: type == "stopped"
},
chunks: chunks,
files: data.files.map(function(e) { e.size = changeLength(e.length, "B"); return e }),
@ -410,7 +420,6 @@ function updateDownloadTemplates(elem, ctx) {
html += '<li class="label">' + ctx.files[i].path + ' (' + ctx.files[i].size + ')</li>';
}
elem.find('.download-files').html(html);
console.log(html);
// update progress bar
elem.find('.full-progress .bar').css('width', ctx.percentage + '%');
@ -464,7 +473,7 @@ function deleteDownloadTemplates($top_elem, data) {
}
}
function refreshDownloadTemplates(top_elem, data) {
var down_template = $('#download_' + top_elem + '_template').text(),
var down_template = $('#download_template').text(),
new_items = [],
$top_elem = $('#' + top_elem + '_downloads');

View File

@ -40,7 +40,7 @@ app.factory('$jsoncall', ['$', '$json', '$base64', function($, JSON, base64) {
// check if authentication details are given, if yes then use a hack to support
// http authentication otherwise emit error
if (!rpc.serverConf.auth) {
console.log("no user name and still error!!!");
console.log("jsonrpc disconnect!!!");
return opts.error();
}

View File

@ -1,19 +1,20 @@
app.factory('$rpc', ['$syscall', '$globalTimeout', function(syscall, time) {
var subscriptions = [],
timeout = null,
forceNextUpdate = false;
var subscriptions = []
, configurations = [{ host: 'localhost', port: 6800 }]
, timeout = null
, forceNextUpdate = false;
syscall.init({
host: 'localhost',
port: 6800
});
// update is implemented such that
// only one syscall at max is ongoing
// (i.e. serially) so should be private
// to maintain that invariant
var update = function() {
if (!subscriptions.length) return;
if (!subscriptions.length)
return;
if (configurations.length)
syscall.init(configurations.pop());
subscriptions = _.filter(subscriptions, function(e) { return !!e });
var params = _.map(subscriptions, function(s) {
@ -27,6 +28,8 @@ app.factory('$rpc', ['$syscall', '$globalTimeout', function(syscall, time) {
name: 'system.multicall',
params: [params],
success: function(data) {
// configuration worked, leave this as it is
configurations = [];
_.each(data.result, function(d, i) {
var handle = subscriptions[i];
if (handle) {
@ -44,17 +47,24 @@ app.factory('$rpc', ['$syscall', '$globalTimeout', function(syscall, time) {
timeout = setTimeout(update, time);
},
error: function() {
// TODO: implement a retry error handler
// which would also look for other suitable
// connection configurations for the connection
// If some proposed configurations are still in the pipeline then retry
if (configurations.length) update();
else {
console.log('cannot connect!!!');
timeout = setTimeout(update, time);
}
}
});
}
return {
// change the connection configuration,
// for all options read rpc/syscall.js
// conf can be configuration or array of configurations,
// each one will be tried one after the other till success,
// for all options for one conf read rpc/syscall.js
configure: function(conf) {
syscall.init(conf);
if (conf instanceof Array)
configurations = conf;
else
configurations = [conf];
},
// syscall is done only once
once: function(name, params, cb) {

View File

@ -1,5 +1,5 @@
app.factory('$sockcall', ['$_', '$json', '$name', '$utils', function(_, JSON, name, utils) {
return {
var sockRPC = {
// true when sockrpc is ready to be used,
// false when either initializing
// or no support for web sockets
@ -18,14 +18,14 @@ app.factory('$sockcall', ['$_', '$json', '$name', '$utils', function(_, JSON, na
scheme: 'ws',
// called when a connection error occurs
onerror: function() {
_.each(this.handles, function(h) { h.error() });
this.handles = [];
onerror: function(err) {
_.each(sockRPC.handles, function(h) { h.error() });
sockRPC.handles = [];
},
// when connection opens
onopen: function() {
this.initialized = true;
sockRPC.initialized = true;
},
@ -35,10 +35,10 @@ app.factory('$sockcall', ['$_', '$json', '$name', '$utils', function(_, JSON, na
// reverse loop because we are deleting elements
// while looping over the old items
for (var i = this.handles.length - 1; i >= 0; i--) {
if (this.handles[i].id === data.id) {
this.handles[i].success(data);
this.handles.splice(i, 1);
for (var i = sockRPC.handles.length - 1; i >= 0; i--) {
if (sockRPC.handles[i].id === data.id) {
sockRPC.handles[i].success(data);
sockRPC.handles.splice(i, 1);
return;
}
}
@ -49,18 +49,18 @@ app.factory('$sockcall', ['$_', '$json', '$name', '$utils', function(_, JSON, na
var data = {
jsonrpc: 2.0,
id: name + '_' + utils.randStr(),
method: opts.func,
method: opts.name,
params: opts.params && opts.params.length ? opts.params : undefined
};
if (data.params && !data.params.length) data.params = undefined;
this.handles.push({
sockRPC.handles.push({
success: opts.success || angular.noop,
error: opts.error || angular.noop,
id: data.id
});
this.sock.send( JSON.stringify(data) );
sockRPC.sock.send( JSON.stringify(data) );
},
// should be called initially to start using the sock rpc
@ -68,26 +68,29 @@ app.factory('$sockcall', ['$_', '$json', '$name', '$utils', function(_, JSON, na
if (typeof WebSocket == "undefined") {
return;
}
this.conf = conf || this.conf;
this.initialized = false;
sockRPC.conf = conf || sockRPC.conf;
sockRPC.initialized = false;
this.scheme = this.conf.encryption ? 'wss' : 'ws';
sockRPC.scheme = sockRPC.conf.encryption ? 'wss' : 'ws';
if (this.sock) {
this.onopen = this.sock.onmessage = this.sock.onerror = this.sock.onclose = null;
this.onerror();
if (sockRPC.sock) {
sockRPC.onopen = sockRPC.sock.onmessage = sockRPC.sock.onerror = sockRPC.sock.onclose = null;
sockRPC.onerror();
}
try {
this.sock = new WebSocket(this.scheme + '://' + conf.host + ':' + conf.port + '/jsonrpc');
this.sock.onopen = this.onopen;
this.sock.onclose = this.sock.onerror = this.onerror;
this.sock.onmessage = this.onmessage;
sockRPC.sock = new WebSocket(sockRPC.scheme + '://' + conf.host + ':' + conf.port + '/jsonrpc');
sockRPC.sock.onopen = sockRPC.onopen;
sockRPC.sock.onclose = sockRPC.sock.onerror = sockRPC.onerror;
sockRPC.sock.onmessage = sockRPC.onmessage;
}
catch (ex) {
// ignoring IE securty exception on local ip addresses
console.log('not using websocket for aria2 rpc due to: ', ex);
}
},
};
return sockRPC;
}]);

View File

@ -32,10 +32,12 @@ app.factory('$syscall', ['$log', '$jsoncall', '$sockcall', function(log, jsonRPC
opts.success = opts.success || angular.noop;
opts.error = opts.error || angular.noop;
if (sockRPC.initialized)
if (sockRPC.initialized) {
return sockRPC.invoke(opts);
else
}
else {
return jsonRPC.invoke(opts);
}
}
};
}]);

View File

@ -8,13 +8,56 @@ app.factory('$utils', function() {
}
return str.join("");
},
mixin: function(fromObj, toObj) {
for (var key in toObj) {
if (toObj.hasOwnProperty(key) && fromObj[key]) {
toObj[key] = fromObj[key];
// change time units
changeTime: function(time) {
time = parseInt(time);
if (!time) return " infinite";
if (time < 60) return time + " s";
else if (time < 60*60) return (time/60).toFixed(2) + " min";
else if (time < 60*60*24) return (time/(60*60)).toFixed(2) + " hours";
else return (time/(60*60*24)).toFixed(2) + " days!";
},
// change length units
changeLength: function(len, pref) {
len = parseInt(len);
if(len <= (1<<10)) return len + " " + pref;
else if(len <= (1<<20)) return (len/(1<<10)).toFixed(1) + " K" + pref;
else if(len <= (1<<30)) return (len/(1<<20)).toFixed(1) + " M" + pref;
else return (len/(1<<30)).toFixed(1) + " G" + pref;
},
// get download chunks from aria2 bitfield
getChunksFromHex: function(bitfield, numOfPieces) {
var chunks = [], len = 0, numPieces = parseInt(numOfPieces);
var totalDownloaded = 0;
if (numPieces > 1) {
var chunk_ratio = 1 / numPieces;
var piecesProcessed = 0;
for (var i = 0; i < bitfield.length; i++) {
var hex = parseInt(bitfield[i], 16);
for (var j = 1; j <= 4; j++) {
var bit = hex & (1 << (4 - j));
if (bit) totalDownloaded++;
var prog = !!bit;
if (len >= 1 && chunks[len - 1].show == prog) {
chunks[len - 1].ratio += chunk_ratio;
}
else {
chunks.push({
ratio: chunk_ratio,
show: prog
});
len++;
}
piecesProcessed++;
if (piecesProcessed == numPieces)
return chunks;
}
}
}
return toObj;
return chunks;
}
};
});