refactoed rpc and templates with ui hints for download status
This commit is contained in:
parent
50218debae
commit
e64b3fbd66
184
index.html
184
index.html
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}]);
|
||||
|
|
15
js/script.js
15
js/script.js
|
@ -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');
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}]);
|
||||
|
||||
|
|
|
@ -32,11 +32,13 @@ 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);
|
||||
}
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue
Block a user