support multi host

master
MaysWind 2017-03-19 23:36:14 +08:00
parent b4faa50dca
commit f7908c9a60
13 changed files with 317 additions and 53 deletions

View File

@ -41,10 +41,24 @@
<body class="hold-transition skin-aria-ng sidebar-mini fixed">
<div class="wrapper" ng-controller="MainController" ng-swipe-left="swipeActions.leftSwipe()" ng-swipe-right="swipeActions.rightSwipe()" ng-swipe-disable-mouse>
<header class="main-header">
<a class="logo" href="#">
<span class="logo-mini">Aria</span>
<span class="logo-lg" title="AriaNg %%GULP_INJECT_VERSION%%">AriaNg</span>
</a>
<div class="logo">
<div class="logo-mini">AriaNg</div>
<div class="logo-lg" title="AriaNg %%GULP_INJECT_VERSION%%">
<div class="dropdown">
<span class="dropdown-toggle" data-toggle="dropdown">
<span class="logo-lg-title">AriaNg</span><span class="caret"></span>
</span>
<ul class="dropdown-menu dropdown-menu-right" role="menu">
<li ng-repeat="setting in rpcSettings" ng-class="{'active': setting.isDefault}">
<a class="pointer-cursor" ng-click="switchRpcSetting(setting)">
<span ng-bind="(setting.rpcAlias ? setting.rpcAlias : setting.rpcHost + ':' + setting.rpcPort)">RPC</span>
<i class="fa" ng-class="{'fa-check': setting.isDefault}"></i>
</a>
</li>
</ul>
</div>
</div>
</div>
<nav class="navbar navbar-static-top" role="navigation">
<div class="navbar-toolbar">

View File

@ -11,7 +11,6 @@ Connecting=连接中
Connected=已连接
Not Connected=未连接
Global=全局
RPC=RPC
New=新建
Start=开始任务
Pause=暂停任务
@ -127,6 +126,7 @@ Tips: You can use the "noprefix" tag to ignore the prefix, "nosuffix" tag ignore
Example: ${downspeed:noprefix:nosuffix:scale\=1}=示例: ${downspeed:noprefix:nosuffix:scale\=1}
Page Title Refresh Interval=页面标题刷新间隔
Enable Browser Notification=启用浏览器通知
Aria2 RPC Alias=Aria2 RPC 别名
Aria2 RPC Host=Aria2 RPC 主机
Aria2 RPC Port=Aria2 RPC 端口
Aria2 RPC Interface=Aria2 RPC 接口
@ -135,6 +135,10 @@ Aria2 RPC Http Request Method=Aria2 RPC Http 请求方法
POST method only supports aria2 v1.15.2 and above.=POST 方法仅支持 aria2 v1.15.2 及以上.
Aria2 RPC Secret Token=Aria2 RPC 密钥
Aria2 RPC Address=Aria2 RPC 地址
Set Default=设为默认
Delete RPC Setting=删除 RPC 设置
Add New RPC Setting=添加新 RPC 配置
Are you sure you want to remove this rpc setting?=您是否要删除当前 RPC 设置?
Global Stat Refresh Interval=全局状态刷新间隔
Download Task Refresh Interval=下载任务刷新间隔
Supported Placeholder=支持的占位符

View File

@ -20,12 +20,14 @@
title: '${downspeed}, ${upspeed} - ${title}',
titleRefreshInterval: 5000,
browserNotification: false,
rpcAlias: '',
rpcHost: '',
rpcPort: '6800',
rpcInterface: 'jsonrpc',
protocol: 'http',
httpMethod: 'POST',
secret: '',
extendRpcServers: [],
globalStatRefreshInterval: 1000,
downloadTaskRefreshInterval: 1000
});

View File

@ -15,7 +15,6 @@
'Connected': 'Connected',
'Not Connected': 'Not Connected',
'Global': 'Global',
'RPC': 'RPC',
'New': 'New',
'Start': 'Start',
'Pause': 'Pause',
@ -131,6 +130,7 @@
'Example: ${downspeed:noprefix:nosuffix:scale=1}': 'Example: ${downspeed:noprefix:nosuffix:scale=1}',
'Page Title Refresh Interval': 'Page Title Refresh Interval',
'Enable Browser Notification': 'Enable Browser Notification',
'Aria2 RPC Alias': 'Aria2 RPC Alias',
'Aria2 RPC Host': 'Aria2 RPC Host',
'Aria2 RPC Port': 'Aria2 RPC Port',
'Aria2 RPC Interface': 'Aria2 RPC Interface',
@ -139,6 +139,10 @@
'POST method only supports aria2 v1.15.2 and above.': 'POST method only supports aria2 v1.15.2 and above.',
'Aria2 RPC Secret Token': 'Aria2 RPC Secret Token',
'Aria2 RPC Address': 'Aria2 RPC Address',
'Set Default': 'Set Default',
'Delete RPC Setting': 'Delete RPC Setting',
'Add New RPC Setting': 'Add New RPC Setting',
'Are you sure you want to remove this rpc setting?': 'Are you sure you want to remove this rpc setting?',
'Global Stat Refresh Interval': 'Global Stat Refresh Interval',
'Download Task Refresh Interval': 'Download Task Refresh Interval',
'Supported Placeholder': 'Supported Placeholder',

View File

@ -1,7 +1,7 @@
(function () {
'use strict';
angular.module('ariaNg').controller('MainController', ['$rootScope', '$scope', '$route', '$location', '$document', '$interval', 'aria2RpcErrors', 'ariaNgCommonService', 'ariaNgSettingService', 'ariaNgTitleService', 'ariaNgMonitorService', 'ariaNgNotificationService', 'aria2TaskService', 'aria2SettingService', function ($rootScope, $scope, $route, $location, $document, $interval, aria2RpcErrors, ariaNgCommonService, ariaNgSettingService, ariaNgTitleService, ariaNgMonitorService, ariaNgNotificationService, aria2TaskService, aria2SettingService) {
angular.module('ariaNg').controller('MainController', ['$rootScope', '$scope', '$route', '$window', '$location', '$document', '$interval', 'aria2RpcErrors', 'ariaNgCommonService', 'ariaNgSettingService', 'ariaNgTitleService', 'ariaNgMonitorService', 'ariaNgNotificationService', 'aria2TaskService', 'aria2SettingService', function ($rootScope, $scope, $route, $window, $location, $document, $interval, aria2RpcErrors, ariaNgCommonService, ariaNgSettingService, ariaNgTitleService, ariaNgMonitorService, ariaNgNotificationService, aria2TaskService, aria2SettingService) {
var pageTitleRefreshPromise = null;
var globalStatRefreshPromise = null;
@ -36,6 +36,8 @@
data: ariaNgMonitorService.getGlobalStatsData()
};
$scope.rpcSettings = ariaNgSettingService.getAllRpcSettings();
$scope.isTaskSelected = function () {
return $rootScope.taskContext.getSelectedTaskIds().length > 0;
};
@ -211,6 +213,15 @@
return orderType.equals(targetType);
};
$scope.switchRpcSetting = function (setting) {
if (setting.isDefault) {
return;
}
ariaNgSettingService.setDefaultRpcSetting(setting);
$window.location.reload();
};
if (ariaNgSettingService.getTitleRefreshInterval() > 0) {
pageTitleRefreshPromise = $interval(function () {
refreshPageTitle();

View File

@ -1,8 +1,7 @@
(function () {
'use strict';
angular.module('ariaNg').controller('AriaNgSettingsController', ['$rootScope', '$scope', '$routeParams', '$interval', '$timeout', 'ariaNgLanguages', 'ariaNgCommonService', 'ariaNgSettingService', 'ariaNgMonitorService', 'ariaNgNotificationService', 'ariaNgTitleService', function ($rootScope, $scope, $routeParams, $interval, $timeout, ariaNgLanguages, ariaNgCommonService, ariaNgSettingService, ariaNgMonitorService, ariaNgNotificationService, ariaNgTitleService) {
var tabOrders = ['global', 'rpc'];
angular.module('ariaNg').controller('AriaNgSettingsController', ['$rootScope', '$scope', '$routeParams', '$window', '$interval', '$timeout', 'ariaNgLanguages', 'ariaNgCommonService', 'ariaNgSettingService', 'ariaNgMonitorService', 'ariaNgNotificationService', 'ariaNgTitleService', function ($rootScope, $scope, $routeParams, $window, $interval, $timeout, ariaNgLanguages, ariaNgCommonService, ariaNgSettingService, ariaNgMonitorService, ariaNgNotificationService, ariaNgTitleService) {
var extendType = $routeParams.extendType;
var getFinalTitle = function () {
@ -17,13 +16,26 @@
trueFalseOptions: [{name: 'True', value: true}, {name: 'False', value: false}],
showRpcSecret: false,
settings: ariaNgSettingService.getAllOptions(),
sessionSettings: ariaNgSettingService.getAllSessionOptions()
sessionSettings: ariaNgSettingService.getAllSessionOptions(),
rpcSettings: ariaNgSettingService.getAllRpcSettings()
};
$scope.context.showDebugMode = $scope.context.sessionSettings.debugMode || extendType === 'debug';
$scope.changeTab = function (tabName) {
$scope.context.currentTab = tabName;
$scope.changeGlobalTab = function () {
$scope.context.currentTab = 'global';
};
$scope.isCurrentGlobalTab = function () {
return $scope.context.currentTab === 'global';
};
$scope.changeRpcTab = function (rpcIndex) {
$scope.context.currentTab = 'rpc' + rpcIndex;
};
$scope.isCurrentRpcTab = function (rpcIndex) {
return $scope.context.currentTab === 'rpc' + rpcIndex;
};
$scope.updateTitlePreview = function () {
@ -31,10 +43,14 @@
};
$rootScope.swipeActions.extentLeftSwipe = function () {
var tabIndex = tabOrders.indexOf($scope.context.currentTab);
var tabIndex = -1;
if (tabIndex < tabOrders.length - 1) {
$scope.changeTab(tabOrders[tabIndex + 1]);
if (!$scope.isCurrentGlobalTab()) {
tabIndex = parseInt($scope.context.currentTab.substring(3));
}
if (tabIndex < $scope.context.rpcSettings.length - 1) {
$scope.changeRpcTab(tabIndex + 1);
return true;
} else {
return false;
@ -42,10 +58,17 @@
};
$rootScope.swipeActions.extentRightSwipe = function () {
var tabIndex = tabOrders.indexOf($scope.context.currentTab);
var tabIndex = -1;
if (!$scope.isCurrentGlobalTab()) {
tabIndex = parseInt($scope.context.currentTab.substring(3));
}
if (tabIndex > 0) {
$scope.changeTab(tabOrders[tabIndex - 1]);
$scope.changeRpcTab(tabIndex - 1);
return true;
} else if (tabIndex === 0) {
$scope.changeGlobalTab();
return true;
} else {
return false;
@ -54,9 +77,41 @@
$scope.settingService = ariaNgSettingService;
$scope.addNewRpcSetting = function () {
var newRpcSetting = ariaNgSettingService.addNewRpcSetting();
$scope.context.rpcSettings.push(newRpcSetting);
$scope.changeRpcTab($scope.context.rpcSettings.length - 1);
};
$scope.updateRpcSetting = function (setting, field) {
ariaNgSettingService.updateRpcSetting(setting, field);
};
$scope.removeRpcSetting = function (setting) {
ariaNgCommonService.confirm('Confirm Remove', 'Are you sure you want to remove this rpc setting?', 'warning', function () {
var index = $scope.context.rpcSettings.indexOf(setting);
ariaNgSettingService.removeRpcSetting(setting);
$scope.context.rpcSettings.splice(index, 1);
if (index >= $scope.context.rpcSettings.length) {
$scope.changeRpcTab($scope.context.rpcSettings.length - 1);
}
});
};
$scope.setDefaultRpcSetting = function (setting) {
if (setting.isDefault) {
return;
}
ariaNgSettingService.setDefaultRpcSetting(setting);
$window.location.reload();
};
$scope.isSupportNotification = function () {
return ariaNgNotificationService.isSupportBrowserNotification() &&
ariaNgSettingService.isUseWebSocket($scope.context.settings.protocol);
ariaNgSettingService.isCurrentRpcUseWebSocket($scope.context.settings.protocol);
};
$scope.setEnableBrowserNotification = function (value) {

View File

@ -3,7 +3,7 @@
angular.module('ariaNg').controller('Aria2StatusController', ['$rootScope', '$scope', 'ariaNgCommonService', 'ariaNgSettingService', 'aria2SettingService', function ($rootScope, $scope, ariaNgCommonService, ariaNgSettingService, aria2SettingService) {
$scope.context = {
host: ariaNgSettingService.getJsonRpcUrl(),
host: ariaNgSettingService.getCurrentRpcUrl(),
status: 'Connecting',
serverStatus: null
};

View File

@ -2,8 +2,8 @@
'use strict';
angular.module('ariaNg').factory('aria2HttpRpcService', ['$http', 'base64', 'ariaNgSettingService', 'ariaNgLogService', function ($http, base64, ariaNgSettingService, ariaNgLogService) {
var rpcUrl = ariaNgSettingService.getJsonRpcUrl();
var method = ariaNgSettingService.getHttpMethod();
var rpcUrl = ariaNgSettingService.getCurrentRpcUrl();
var method = ariaNgSettingService.getCurrentRpcHttpMethod();
var getUrlWithQueryString = function (url, parameters) {
if (!url || url.length < 1) {

View File

@ -2,9 +2,9 @@
'use strict';
angular.module('ariaNg').factory('aria2RpcService', ['$q', 'aria2RpcConstants', 'aria2RpcErrors', 'ariaNgCommonService', 'ariaNgSettingService', 'ariaNgLogService', 'aria2HttpRpcService', 'aria2WebSocketRpcService', function ($q, aria2RpcConstants, aria2RpcErrors, ariaNgCommonService, ariaNgSettingService, ariaNgLogService, aria2HttpRpcService, aria2WebSocketRpcService) {
var rpcImplementService = ariaNgSettingService.isUseWebSocket() ? aria2WebSocketRpcService : aria2HttpRpcService;
var rpcImplementService = ariaNgSettingService.isCurrentRpcUseWebSocket() ? aria2WebSocketRpcService : aria2HttpRpcService;
var isConnected = false;
var secret = ariaNgSettingService.getSecret();
var secret = ariaNgSettingService.getCurrentRpcSecret();
var onFirstSuccessCallbacks = [];
var onConnectSuccessCallbacks = [];

View File

@ -2,7 +2,7 @@
'use strict';
angular.module('ariaNg').factory('aria2WebSocketRpcService', ['$q', '$websocket', 'ariaNgSettingService', 'ariaNgLogService', function ($q, $websocket, ariaNgSettingService, ariaNgLogService) {
var rpcUrl = ariaNgSettingService.getJsonRpcUrl();
var rpcUrl = ariaNgSettingService.getCurrentRpcUrl();
var socketClient = null;
var sendIdStates = {};

View File

@ -1,7 +1,7 @@
(function () {
'use strict';
angular.module('ariaNg').factory('ariaNgSettingService', ['$window', '$location', '$filter', '$translate', 'base64', 'amMoment', 'localStorageService', 'ariaNgConstants', 'ariaNgDefaultOptions', 'ariaNgLanguages', function ($window, $location, $filter, $translate, base64, amMoment, localStorageService, ariaNgConstants, ariaNgDefaultOptions, ariaNgLanguages) {
angular.module('ariaNg').factory('ariaNgSettingService', ['$window', '$location', '$filter', '$translate', 'base64', 'amMoment', 'localStorageService', 'ariaNgConstants', 'ariaNgDefaultOptions', 'ariaNgLanguages', 'ariaNgCommonService', function ($window, $location, $filter, $translate, base64, amMoment, localStorageService, ariaNgConstants, ariaNgDefaultOptions, ariaNgLanguages, ariaNgCommonService) {
var onFirstVisitCallbacks = [];
var sessionSettings = {
debugMode: false
@ -65,7 +65,7 @@
var getOption = function (key) {
var options = getOptions();
if (angular.isUndefined(options[key])) {
if (angular.isUndefined(options[key]) && angular.isDefined(ariaNgDefaultOptions[key])) {
options[key] = ariaNgDefaultOptions[key];
setOptions(options);
}
@ -80,6 +80,26 @@
setOptions(options);
};
var cloneRpcSetting = function (setting) {
return {
rpcAlias: setting.rpcAlias,
rpcHost: setting.rpcHost,
rpcPort: setting.rpcPort,
rpcInterface: setting.rpcInterface,
protocol: setting.protocol,
httpMethod: setting.httpMethod,
secret: setting.secret
};
};
var createNewRpcSetting = function () {
var setting = cloneRpcSetting(ariaNgDefaultOptions);
setting.rpcId = ariaNgCommonService.generateUniqueId();
setting.rpcHost = getDefaultRpcHost();
return setting;
};
return {
getAllOptions: function () {
var options = angular.extend({}, ariaNgDefaultOptions, getOptions());
@ -92,8 +112,41 @@
options.secret = base64.decode(options.secret);
}
if (angular.isArray(options.extendRpcServers)) {
for (var i = 0; i < options.extendRpcServers.length; i++) {
var rpcSetting = options.extendRpcServers[i];
if (!rpcSetting.rpcHost) {
rpcSetting.rpcHost = getDefaultRpcHost();
}
if (rpcSetting.secret) {
rpcSetting.secret = base64.decode(rpcSetting.secret);
}
}
}
return options;
},
getAllRpcSettings: function () {
var result = [];
var options = this.getAllOptions();
var defaultRpcSetting = cloneRpcSetting(options);
defaultRpcSetting.isDefault = true;
result.push(defaultRpcSetting);
if (angular.isArray(options.extendRpcServers)) {
for (var i = 0; i < options.extendRpcServers.length; i++) {
var rpcSetting = cloneRpcSetting(options.extendRpcServers[i]);
rpcSetting.rpcId = options.extendRpcServers[i].rpcId;
rpcSetting.isDefault = false;
result.push(rpcSetting);
}
}
return result;
},
getAllSessionOptions: function () {
return angular.copy(sessionSettings);
},
@ -139,7 +192,7 @@
setBrowserNotification: function (value) {
setOption('browserNotification', value);
},
getJsonRpcUrl: function () {
getCurrentRpcUrl: function () {
var protocol = getOption('protocol');
var rpcHost = getOption('rpcHost');
var rpcPort = getOption('rpcPort');
@ -151,44 +204,126 @@
return protocol + '://' + rpcHost + ':' + rpcPort + '/' + rpcInterface;
},
setRpcHost: function (value) {
setOption('rpcHost', value);
},
setRpcPort: function (value) {
setOption('rpcPort', Math.max(parseInt(value), 0));
},
setRpcInterface: function (value) {
setOption('rpcInterface', value);
},
getProtocol: function () {
getCurrentRpcProtocol: function () {
return getOption('protocol');
},
setProtocol: function (value) {
setOption('protocol', value);
},
getHttpMethod: function () {
getCurrentRpcHttpMethod: function () {
return getOption('httpMethod');
},
setHttpMethod: function (value) {
setOption('httpMethod', value);
},
isUseWebSocket: function (protocol) {
isCurrentRpcUseWebSocket: function (protocol) {
if (!protocol) {
protocol = this.getProtocol();
protocol = this.getCurrentRpcProtocol();
}
return protocol === 'ws' || protocol === 'wss';
},
getSecret: function () {
getCurrentRpcSecret: function () {
var value = getOption('secret');
return (value ? base64.decode(value) : value);
},
setSecret: function (value) {
if (value) {
value = base64.encode(value);
addNewRpcSetting: function () {
var options = getOptions();
if (!angular.isArray(options.extendRpcServers)) {
options.extendRpcServers = [];
}
setOption('secret', value);
var newRpcSetting = createNewRpcSetting();
options.extendRpcServers.push(newRpcSetting);
setOptions(options);
return newRpcSetting;
},
updateRpcSetting: function (setting, field) {
if (!setting) {
return setting;
}
var updatedSetting = cloneRpcSetting(setting);
if (angular.isUndefined(updatedSetting[field])) {
return setting;
}
var value = updatedSetting[field];
if (field === 'rpcPort') {
value = Math.max(parseInt(value), 0);
} else if (field === 'secret') {
if (value) {
value = base64.encode(value);
}
}
if (setting.isDefault) {
setOption(field, value);
return setting;
} else {
var options = getOptions();
if (!angular.isArray(options.extendRpcServers)) {
return setting;
}
for (var i = 0; i < options.extendRpcServers.length; i++) {
if (options.extendRpcServers[i].rpcId === setting.rpcId) {
options.extendRpcServers[i][field] = value;
break;
}
}
setOptions(options);
return setting;
}
},
removeRpcSetting: function (setting) {
var options = getOptions();
if (!angular.isArray(options.extendRpcServers)) {
return setting;
}
for (var i = 0; i < options.extendRpcServers.length; i++) {
if (options.extendRpcServers[i].rpcId === setting.rpcId) {
options.extendRpcServers.splice(i, 1);
break;
}
}
setOptions(options);
return setting;
},
setDefaultRpcSetting: function (setting) {
var options = getOptions();
var currentSetting = cloneRpcSetting(options);
currentSetting.rpcId = ariaNgCommonService.generateUniqueId();
if (!angular.isArray(options.extendRpcServers)) {
options.extendRpcServers = [];
}
var newDefaultSetting = null;
for (var i = 0; i < options.extendRpcServers.length; i++) {
if (options.extendRpcServers[i].rpcId === setting.rpcId) {
newDefaultSetting = cloneRpcSetting(options.extendRpcServers[i]);
options.extendRpcServers.splice(i, 1);
break;
}
}
if (newDefaultSetting) {
options.extendRpcServers.splice(0, 0, currentSetting);
options = angular.extend(options, newDefaultSetting);
}
setOptions(options);
return setting;
},
getGlobalStatRefreshInterval: function () {
return getOption('globalStatRefreshInterval');

View File

@ -15,12 +15,24 @@ td {
vertical-align: middle !important;
}
.skin-aria-ng .main-header .logo {
overflow: visible;
}
.skin-aria-ng .main-header .logo .dropdown-menu {
z-index: 2000;
}
.main-header .navbar .navbar-searchbar {
padding-top: 8px;
padding-right: 20px;
float: right;
}
.main-header .logo .logo-lg {
cursor: pointer;
}
.content-wrapper > .content-body {
overflow-y: scroll;
}

View File

@ -85,10 +85,36 @@
border-bottom: 1px solid #59636b;
}
.skin-aria-ng .main-header .logo:hover {
.skin-aria-ng .main-header .logo .logo-lg:hover {
color: #cccccc;
}
.skin-aria-ng .main-header .logo .logo-lg .logo-lg-title {
margin-right: 2px;
}
.skin-aria-ng .main-header .logo .dropdown-menu {
margin-top: -1px;
border-color: #59636b;
background-color: #3c4852;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.skin-aria-ng .main-header .logo .dropdown-menu > li > a {
color: #a2b5b9;
}
.skin-aria-ng .main-header .logo .dropdown-menu > li:hover > a {
color: #dfdfdf;
background-color: #313a42;
}
.skin-aria-ng .main-header .logo .dropdown-menu > li.active > a {
color: #5399e8;
background-color: #252c30;
}
.skin-aria-ng .content-header {
background: transparent;
}
@ -159,7 +185,8 @@
}
.skin-aria-ng .sidebar-menu i.fa {
font-size: 16px;
font-size: 18px;
margin-right: 2px;
}
.skin-aria-ng .sidebar a {