diff --git a/app/index.html b/app/index.html index d908aec..c070e4a 100644 --- a/app/index.html +++ b/app/index.html @@ -44,13 +44,13 @@
  • -
  • - +
  • +
  • -
  • - +
  • +
  • @@ -61,7 +61,7 @@
  • -
  • +
  • @@ -259,31 +259,34 @@ - - - - - - - + + + + + + + - - - + + + + - - - - + + + + + + diff --git a/app/scripts/core/aria2options.js b/app/scripts/config/aria2options.js similarity index 100% rename from app/scripts/core/aria2options.js rename to app/scripts/config/aria2options.js diff --git a/app/scripts/config/configuration.js b/app/scripts/config/configuration.js new file mode 100644 index 0000000..2e99488 --- /dev/null +++ b/app/scripts/config/configuration.js @@ -0,0 +1,18 @@ +(function () { + 'use strict'; + + angular.module('ariaNg').config(['$translateProvider', 'localStorageServiceProvider', 'ariaNgConstants', function ($translateProvider, localStorageServiceProvider, ariaNgConstants) { + localStorageServiceProvider + .setPrefix(ariaNgConstants.appPrefix) + .setStorageType('localStorage') + .setStorageCookie(365, '/'); + + $translateProvider.useStaticFilesLoader({ + prefix: 'langs/', + suffix: '.json' + }).useLoaderCache(true) + .preferredLanguage('en-US') + .fallbackLanguage('en-US') + .useSanitizeValueStrategy('escape'); + }]); +})(); diff --git a/app/scripts/core/constants.js b/app/scripts/config/constants.js similarity index 87% rename from app/scripts/core/constants.js rename to app/scripts/config/constants.js index b042886..2f69299 100644 --- a/app/scripts/core/constants.js +++ b/app/scripts/config/constants.js @@ -15,6 +15,7 @@ downloadTaskRefreshInterval: 1000 }).constant('aria2RpcConstants', { rpcServiceVersion: '2.0', - rpcServiceName: 'aria2' + rpcServiceName: 'aria2', + rpcSystemServiceName: 'system' }); })(); diff --git a/app/scripts/config/initiator.js b/app/scripts/config/initiator.js new file mode 100644 index 0000000..126136e --- /dev/null +++ b/app/scripts/config/initiator.js @@ -0,0 +1,14 @@ +(function () { + 'use strict'; + + angular.module('ariaNg').run(['amMoment', 'moment', 'ariaNgSettingService', function (amMoment, moment, ariaNgSettingService) { + var language = ariaNgSettingService.getLanguage(); + + moment.updateLocale('zh-cn', { + week: null + }); + + amMoment.changeLocale(language); + ariaNgSettingService.applyLanguage(language); + }]); +})(); diff --git a/app/scripts/core/lang-default.js b/app/scripts/config/language-default.js similarity index 100% rename from app/scripts/core/lang-default.js rename to app/scripts/config/language-default.js diff --git a/app/scripts/core/lang-confs.js b/app/scripts/config/languages.js similarity index 100% rename from app/scripts/core/lang-confs.js rename to app/scripts/config/languages.js diff --git a/app/scripts/controllers/list.js b/app/scripts/controllers/list.js index fd47c9c..e95899b 100644 --- a/app/scripts/controllers/list.js +++ b/app/scripts/controllers/list.js @@ -1,48 +1,30 @@ (function () { 'use strict'; - angular.module('ariaNg').controller('DownloadListController', ['$rootScope', '$scope', '$window', '$location', '$interval', 'aria2RpcService', 'ariaNgSettingService', 'utils', function ($rootScope, $scope, $window, $location, $interval, aria2RpcService, ariaNgSettingService, utils) { + angular.module('ariaNg').controller('DownloadListController', ['$rootScope', '$scope', '$window', '$location', '$interval', 'ariaNgCommonService', 'ariaNgSettingService', 'ariaNgTaskService', function ($rootScope, $scope, $window, $location, $interval, ariaNgCommonService, ariaNgSettingService, ariaNgTaskService) { var location = $location.path().substring(1); var downloadTaskRefreshPromise = null; var needRequestWholeInfo = true; var refreshDownloadTask = function () { - var invokeMethod = null; - - if (location == 'downloading') { - invokeMethod = aria2RpcService.tellActive; - } else if (location == 'waiting') { - invokeMethod = aria2RpcService.tellWaiting; - } else if (location == 'stopped') { - invokeMethod = aria2RpcService.tellStopped; - } - - if (invokeMethod) { - return invokeMethod({ - requestParams: needRequestWholeInfo ? aria2RpcService.getFullTaskParams() : aria2RpcService.getBasicTaskParams(), - callback: function (result) { - if (!utils.extendArray(result, $rootScope.taskContext.list, 'gid')) { - if (needRequestWholeInfo) { - $rootScope.taskContext.list = result; - needRequestWholeInfo = false; - } else { - needRequestWholeInfo = true; - } - } else { - needRequestWholeInfo = false; - } - - if ($rootScope.taskContext.list && $rootScope.taskContext.list.length > 0) { - for (var i = 0; i < $rootScope.taskContext.list.length; i++) { - utils.processDownloadTask($rootScope.taskContext.list[i]); - } - } + return ariaNgTaskService.getTaskList(location, needRequestWholeInfo, function (result) { + if (!ariaNgCommonService.extendArray(result, $rootScope.taskContext.list, 'gid')) { + if (needRequestWholeInfo) { + $rootScope.taskContext.list = result; + needRequestWholeInfo = false; + } else { + needRequestWholeInfo = true; } - }); - } - }; + } else { + needRequestWholeInfo = false; + } - $rootScope.loadPromise = refreshDownloadTask(); + if ($rootScope.taskContext.list) { + ariaNgTaskService.processDownloadTasks($rootScope.taskContext.list); + $rootScope.taskContext.enableSelectAll = $rootScope.taskContext.list.length > 1; + } + }); + }; $scope.filterByTaskName = function (task) { if (!task || !angular.isString(task.taskName)) { @@ -71,5 +53,7 @@ $interval.cancel(downloadTaskRefreshPromise); } }); + + $rootScope.loadPromise = refreshDownloadTask(); }]); })(); diff --git a/app/scripts/controllers/main.js b/app/scripts/controllers/main.js index 4d704e4..1546eb9 100644 --- a/app/scripts/controllers/main.js +++ b/app/scripts/controllers/main.js @@ -1,76 +1,12 @@ (function () { 'use strict'; - angular.module('ariaNg').controller('MainController', ['$rootScope', '$scope', '$route', '$interval', 'aria2RpcService', 'ariaNgSettingService', 'utils', function ($rootScope, $scope, $route, $interval, aria2RpcService, ariaNgSettingService, utils) { + angular.module('ariaNg').controller('MainController', ['$rootScope', '$scope', '$route', '$interval', 'aria2SettingService', 'ariaNgCommonService', 'ariaNgTaskService', 'ariaNgSettingService', function ($rootScope, $scope, $route, $interval, aria2SettingService, ariaNgCommonService, ariaNgTaskService, ariaNgSettingService) { var globalStatRefreshPromise = null; - var processStatResult = function (stat) { - var activeCount = parseInt(stat.numActive); - var waitingCount = parseInt(stat.numWaiting); - var totalRunningCount = activeCount + waitingCount; - - stat.totalRunningCount = totalRunningCount; - }; - var refreshGlobalStat = function () { - aria2RpcService.getGlobalStat({ - callback: function (result) { - if (result) { - processStatResult(result); - } - - $scope.globalStat = result; - } - }); - }; - - refreshGlobalStat(); - - $scope.startTask = function () { - var gids = $rootScope.taskContext.getSelectedTaskIds(); - - if (!gids || gids.length < 1) { - return; - } - - $rootScope.loadPromise = aria2RpcService.unpauseMulti({ - gids: gids, - callback: function (result) { - $route.reload(); - } - }); - }; - - $scope.pauseTask = function () { - var gids = $rootScope.taskContext.getSelectedTaskIds(); - - if (!gids || gids.length < 1) { - return; - } - - $rootScope.loadPromise = aria2RpcService.forcePauseMulti({ - gids: gids, - callback: function (result) { - $route.reload(); - } - }); - }; - - $scope.removeTask = function () { - var gids = $rootScope.taskContext.getSelectedTaskIds(); - - if (!gids || gids.length < 1) { - return; - } - - utils.confirm('Confirm Remove', 'Are you sure you want to remove the selected task?', 'warning', function () { - - }); - }; - - $scope.clearFinishedTasks = function () { - utils.confirm('Confirm Clear', 'Are you sure you want to clear finished tasks?', 'warning', function () { - + return aria2SettingService.getGlobalStat(function (result) { + $scope.globalStat = result; }); }; @@ -78,7 +14,7 @@ return $rootScope.taskContext.getSelectedTaskIds().length > 0; }; - $scope.isStartableTaskSelected = function () { + $scope.isSpecifiedTaskSelected = function (status) { var selectedTasks = $rootScope.taskContext.getSelectedTasks(); if (selectedTasks.length < 1) { @@ -86,7 +22,7 @@ } for (var i = 0; i < selectedTasks.length; i++) { - if (selectedTasks[i].status == 'paused') { + if (selectedTasks[i].status == status) { return true; } } @@ -94,20 +30,44 @@ return false; }; - $scope.isPausableTaskSelected = function () { - var selectedTasks = $rootScope.taskContext.getSelectedTasks(); + $scope.changeTasksState = function (state) { + var gids = $rootScope.taskContext.getSelectedTaskIds(); - if (selectedTasks.length < 1) { - return false; + if (!gids || gids.length < 1) { + return; } - for (var i = 0; i < selectedTasks.length; i++) { - if (selectedTasks[i].status == 'active') { - return true; - } + var invoke = null; + + if (state == 'start') { + invoke = ariaNgTaskService.startTasks; + } else if (state == 'pause') { + invoke = ariaNgTaskService.pauseTasks; + } else { + return; } - return false; + $rootScope.loadPromise = invoke(gids, function (result) { + $route.reload(); + }); + }; + + $scope.removeTasks = function () { + var gids = $rootScope.taskContext.getSelectedTaskIds(); + + if (!gids || gids.length < 1) { + return; + } + + ariaNgCommonService.confirm('Confirm Remove', 'Are you sure you want to remove the selected task?', 'warning', function () { + + }); + }; + + $scope.clearFinishedTasks = function () { + ariaNgCommonService.confirm('Confirm Clear', 'Are you sure you want to clear finished tasks?', 'warning', function () { + + }); }; $scope.selectAllTasks = function () { @@ -115,8 +75,8 @@ }; $scope.changeDisplayOrder = function (type, autoSetReverse) { - var oldType = utils.parseOrderType(ariaNgSettingService.getDisplayOrder()); - var newType = utils.parseOrderType(type); + var oldType = ariaNgCommonService.parseOrderType(ariaNgSettingService.getDisplayOrder()); + var newType = ariaNgCommonService.parseOrderType(type); if (autoSetReverse && newType.type == oldType.type) { newType.reverse = !oldType.reverse; @@ -126,8 +86,8 @@ }; $scope.isSetDisplayOrder = function (type) { - var orderType = utils.parseOrderType(ariaNgSettingService.getDisplayOrder()); - var targetType = utils.parseOrderType(type); + var orderType = ariaNgCommonService.parseOrderType(ariaNgSettingService.getDisplayOrder()); + var targetType = ariaNgCommonService.parseOrderType(type); return orderType.equals(targetType); }; @@ -143,5 +103,7 @@ $interval.cancel(globalStatRefreshPromise); } }); + + refreshGlobalStat(); }]); })(); diff --git a/app/scripts/controllers/settings-aria2.js b/app/scripts/controllers/settings-aria2.js index 2537052..d7517f3 100644 --- a/app/scripts/controllers/settings-aria2.js +++ b/app/scripts/controllers/settings-aria2.js @@ -1,45 +1,24 @@ (function () { 'use strict'; - angular.module('ariaNg').controller('Aria2SettingsController', ['$rootScope', '$scope', '$location', '$timeout', 'ariaNgConstants', 'aria2GlobalAvailableOptions', 'aria2RpcService', 'utils', function ($rootScope, $scope, $location, $timeout, ariaNgConstants, aria2GlobalAvailableOptions, aria2RpcService, utils) { + angular.module('ariaNg').controller('Aria2SettingsController', ['$rootScope', '$scope', '$location', '$timeout', 'ariaNgConstants', 'ariaNgCommonService', 'aria2SettingService', function ($rootScope, $scope, $location, $timeout, ariaNgConstants, ariaNgCommonService, aria2SettingService) { var location = $location.path().substring($location.path().lastIndexOf('/') + 1); - var pendingSaveRequest = {}; + var pendingSaveRequests = {}; - var getAvailableOptionsKeys = function (location) { - if (location == 'basic') { - return aria2GlobalAvailableOptions.basicOptions; - } else if (location == 'http-ftp-sftp') { - return aria2GlobalAvailableOptions.httpFtpSFtpOptions; - } else if (location == 'http') { - return aria2GlobalAvailableOptions.httpOptions; - } else if (location == 'ftp-sftp') { - return aria2GlobalAvailableOptions.ftpSFtpOptions; - } else if (location == 'bt') { - return aria2GlobalAvailableOptions.btOptions; - } else if (location == 'metalink') { - return aria2GlobalAvailableOptions.metalinkOptions; - } else if (location == 'rpc') { - return aria2GlobalAvailableOptions.rpcOptions; - } else if (location == 'advanced') { - return aria2GlobalAvailableOptions.advancedOptions; - } else { - utils.alert('Type is illegal!'); - return false; - } - }; - - var getAvailableOptions = function (location) { - var keys = getAvailableOptionsKeys(location); + var getAvailableOptions = function (type) { + var keys = aria2SettingService.getAvailableOptionsKeys(type); if (!keys) { + ariaNgCommonService.alert('Type is illegal!'); return; } - return utils.getOptions(keys); + return aria2SettingService.getSpecifiedOptions(keys); }; $scope.optionStatus = {}; $scope.availableOptions = getAvailableOptions(location); + $scope.setGlobalOption = function (option, value, lazySave) { if (!option || !option.key || option.readonly) { return; @@ -47,27 +26,21 @@ var key = option.key; var invoke = function () { - var data = {}; - data[key] = value; - $scope.optionStatus[key] = 'saving'; - return aria2RpcService.changeGlobalOption({ - options: data, - callback: function () { - $scope.optionStatus[key] = 'saved'; - } + return aria2SettingService.setGlobalOption(key, value, function (result) { + $scope.optionStatus[key] = 'saved'; }); }; delete $scope.optionStatus[key]; if (lazySave) { - if (pendingSaveRequest[key]) { - $timeout.cancel(pendingSaveRequest[key]); + if (pendingSaveRequests[key]) { + $timeout.cancel(pendingSaveRequests[key]); } - pendingSaveRequest[key] = $timeout(function () { + pendingSaveRequests[key] = $timeout(function () { invoke(); }, ariaNgConstants.lazySaveTimeout); } else { @@ -76,10 +49,8 @@ }; $rootScope.loadPromise = (function () { - return aria2RpcService.getGlobalOption({ - callback: function (result) { - $scope.globalOptions = result; - } + return aria2SettingService.getGlobalOption(function (result) { + $scope.globalOptions = result; }); })(); }]); diff --git a/app/scripts/controllers/status.js b/app/scripts/controllers/status.js index c3586d8..885c9ca 100644 --- a/app/scripts/controllers/status.js +++ b/app/scripts/controllers/status.js @@ -1,13 +1,11 @@ (function () { 'use strict'; - angular.module('ariaNg').controller('Aria2StatusController', ['$rootScope', '$scope', 'aria2RpcService', function ($rootScope, $scope, aria2RpcService) { + angular.module('ariaNg').controller('Aria2StatusController', ['$rootScope', '$scope', 'aria2SettingService', function ($rootScope, $scope, aria2SettingService) { $rootScope.loadPromise = (function () { - return aria2RpcService.getVersion({ - callback: function (result) { - $scope.serverStatus = result; - } - }) + return aria2SettingService.getServerStatus(function (result) { + $scope.serverStatus = result; + }); })(); }]); })(); diff --git a/app/scripts/controllers/task-detail.js b/app/scripts/controllers/task-detail.js index 53f7a3d..e15b854 100644 --- a/app/scripts/controllers/task-detail.js +++ b/app/scripts/controllers/task-detail.js @@ -1,7 +1,7 @@ (function () { 'use strict'; - angular.module('ariaNg').controller('TaskDetailController', ['$rootScope', '$scope', '$routeParams', '$interval', 'aria2RpcService', 'ariaNgSettingService', 'utils', function ($rootScope, $scope, $routeParams, $interval, aria2RpcService, ariaNgSettingService, utils) { + angular.module('ariaNg').controller('TaskDetailController', ['$rootScope', '$scope', '$routeParams', '$interval', 'ariaNgCommonService', 'ariaNgSettingService', 'ariaNgTaskService', function ($rootScope, $scope, $routeParams, $interval, ariaNgCommonService, ariaNgSettingService, ariaNgTaskService) { var tabOrders = ['overview', 'blocks', 'filelist', 'btpeers']; var downloadTaskRefreshPromise = null; @@ -11,45 +11,32 @@ $scope.healthPercent = 0; - var refreshPeers = function (task) { - return aria2RpcService.getPeers({ - gid: task.gid, - callback: function (result) { - if (!utils.extendArray(result, $scope.peers, 'peerId')) { - $scope.peers = result; - } - - for (var i = 0; i < $scope.peers.length; i++) { - var peer = $scope.peers[i]; - peer.completePercent = utils.estimateCompletedPercentFromBitField(peer.bitfield) * 100; - } - - $scope.healthPercent = utils.estimateHealthPercentFromPeers(task, $scope.peers); + var refreshBtPeers = function (task) { + return ariaNgTaskService.getBtTaskPeers(task.gid, function (result) { + if (!ariaNgCommonService.extendArray(result, $scope.peers, 'peerId')) { + $scope.peers = result; } - }) + + $scope.healthPercent = ariaNgTaskService.estimateHealthPercentFromPeers(task, $scope.peers); + }); }; var refreshDownloadTask = function () { - return aria2RpcService.tellStatus({ - gid: $routeParams.gid, - callback: function (result) { - var task = utils.processDownloadTask(result); - - if (task.status == 'active' && task.bittorrent) { - refreshPeers(task); - } else { - if (tabOrders.indexOf('btpeers') >= 0) { - tabOrders.splice(tabOrders.indexOf('btpeers'), 1); - } + return ariaNgTaskService.getTaskStatus($routeParams.gid, function (result) { + if (result.status == 'active' && result.bittorrent) { + refreshBtPeers(result); + } else { + if (tabOrders.indexOf('btpeers') >= 0) { + tabOrders.splice(tabOrders.indexOf('btpeers'), 1); } - - $scope.task = utils.copyObjectTo(task, $scope.task); - - $rootScope.taskContext.list = [$scope.task]; - $rootScope.taskContext.selected = {}; - $rootScope.taskContext.selected[$scope.task.gid] = true; } - }) + + $scope.task = ariaNgCommonService.copyObjectTo(result, $scope.task); + + $rootScope.taskContext.list = [$scope.task]; + $rootScope.taskContext.selected = {}; + $rootScope.taskContext.selected[$scope.task.gid] = true; + }); }; $rootScope.swipeActions.extentLeftSwipe = function () { @@ -75,17 +62,14 @@ }; $scope.loadTaskOption = function (task) { - $rootScope.loadPromise = aria2RpcService.getOption({ - gid: task.gid, - callback: function (result) { - $scope.options = result; - } + $rootScope.loadPromise = ariaNgTaskService.getTaskOption(task.gid, function (result) { + $scope.options = result; }); }; $scope.changeFileListDisplayOrder = function (type, autoSetReverse) { - var oldType = utils.parseOrderType(ariaNgSettingService.getFileListDisplayOrder()); - var newType = utils.parseOrderType(type); + var oldType = ariaNgCommonService.parseOrderType(ariaNgSettingService.getFileListDisplayOrder()); + var newType = ariaNgCommonService.parseOrderType(type); if (autoSetReverse && newType.type == oldType.type) { newType.reverse = !oldType.reverse; @@ -95,8 +79,8 @@ }; $scope.isSetFileListDisplayOrder = function (type) { - var orderType = utils.parseOrderType(ariaNgSettingService.getFileListDisplayOrder()); - var targetType = utils.parseOrderType(type); + var orderType = ariaNgCommonService.parseOrderType(ariaNgSettingService.getFileListDisplayOrder()); + var targetType = ariaNgCommonService.parseOrderType(type); return orderType.equals(targetType); }; @@ -105,8 +89,6 @@ return ariaNgSettingService.getFileListDisplayOrder(); }; - $rootScope.loadPromise = refreshDownloadTask(); - if (ariaNgSettingService.getDownloadTaskRefreshInterval() > 0) { downloadTaskRefreshPromise = $interval(function () { refreshDownloadTask(); @@ -118,5 +100,7 @@ $interval.cancel(downloadTaskRefreshPromise); } }); + + $rootScope.loadPromise = refreshDownloadTask(); }]); })(); diff --git a/app/scripts/core/config.js b/app/scripts/core/root.js similarity index 77% rename from app/scripts/core/config.js rename to app/scripts/core/root.js index 8605234..52c9822 100644 --- a/app/scripts/core/config.js +++ b/app/scripts/core/root.js @@ -1,34 +1,33 @@ (function () { 'use strict'; - angular.module('ariaNg').config(['$translateProvider', 'localStorageServiceProvider', 'ariaNgConstants', function ($translateProvider, localStorageServiceProvider, ariaNgConstants) { - localStorageServiceProvider - .setPrefix(ariaNgConstants.appPrefix) - .setStorageType('localStorage') - .setStorageCookie(365, '/'); + angular.module('ariaNg').run(['$rootScope', '$location', '$document', 'SweetAlert', function ($rootScope, $location, $document, SweetAlert) { + var isUrlMatchUrl2 = function (url, url2) { + if (url === url2) { + return true; + } - $translateProvider.useStaticFilesLoader({ - prefix: 'langs/', - suffix: '.json' - }).useLoaderCache(true) - .preferredLanguage('en-US') - .fallbackLanguage('en-US') - .useSanitizeValueStrategy('escape'); - }]).run(['$translate', 'amMoment', 'moment', 'ariaNgConstants', 'ariaNgSettingService', function ($translate, amMoment, moment, ariaNgConstants, ariaNgSettingService) { - ariaNgSettingService.applyLanguage(ariaNgSettingService.getLanguage()); + var index = url2.indexOf(url); - moment.updateLocale('zh-cn', { - week: null - }); + if (index !== 0) { + return false; + } + + var lastPart = url2.substring(url.length); + + if (lastPart.indexOf('/') == 0) { + return true; + } + + return false; + }; - amMoment.changeLocale(ariaNgSettingService.getLanguage()); - }]).run(['$rootScope', '$location', '$document', 'SweetAlert', 'ariaNgConstants', 'utils', function ($rootScope, $location, $document, SweetAlert, ariaNgConstants, utils) { var setNavbarSelected = function (location) { angular.element('section.sidebar > ul li').removeClass('active'); angular.element('section.sidebar > ul > li[data-href-match]').each(function (index, element) { var match = angular.element(element).attr('data-href-match'); - if (utils.isUrlMatchUrl2(match, location)) { + if (isUrlMatchUrl2(match, location)) { angular.element(element).addClass('active'); } }); @@ -36,7 +35,7 @@ angular.element('section.sidebar > ul > li.treeview > ul.treeview-menu > li[data-href-match]').each(function (index, element) { var match = angular.element(element).attr('data-href-match'); - if (utils.isUrlMatchUrl2(match, location)) { + if (isUrlMatchUrl2(match, location)) { angular.element(element).addClass('active').parent().parent().addClass('active'); } }); @@ -61,6 +60,7 @@ $rootScope.taskContext = { list: [], selected: {}, + enableSelectAll: false, getSelectedTaskIds: function () { var result = []; @@ -150,6 +150,8 @@ $rootScope.taskContext.selected = {}; } + $rootScope.taskContext.enableSelectAll = false; + SweetAlert.close(); }); diff --git a/app/scripts/core/utils.js b/app/scripts/core/utils.js deleted file mode 100644 index d1c12cb..0000000 --- a/app/scripts/core/utils.js +++ /dev/null @@ -1,310 +0,0 @@ -(function () { - 'use strict'; - - angular.module('ariaNg').factory('utils', ['$location', '$timeout', '$base64', 'SweetAlert', '$translate', 'ariaNgConstants', 'aria2AllOptions', function ($location, $timeout, $base64, SweetAlert, $translate, ariaNgConstants, aria2AllOptions) { - var calculateDownloadRemainTime = function (remainBytes, downloadSpeed) { - if (downloadSpeed == 0) { - return 0; - } - - return remainBytes / downloadSpeed; - }; - - return { - generateUniqueId: function () { - var sourceId = ariaNgConstants.appPrefix + '_' + Math.round(new Date().getTime() / 1000) + '_' + Math.random(); - var hashedId = $base64.encode(sourceId); - - return hashedId; - }, - alert: function (text) { - $timeout(function () { - SweetAlert.swal({ - title: $translate.instant('Error'), - text: $translate.instant(text), - type: 'error', - confirmButtonText: $translate.instant('OK') - }); - }, 100); - }, - confirm: function (title, text, type, callback) { - var options = { - title: $translate.instant(title), - text: $translate.instant(text), - type: type, - showCancelButton: true, - confirmButtonText: $translate.instant('OK'), - cancelButtonText: $translate.instant('Cancel') - }; - - if (type == 'warning') { - options.confirmButtonColor = '#F39C12'; - } - - SweetAlert.swal(options, function (isConfirm) { - if (!isConfirm) { - return; - } - - if (callback) { - callback(); - } - }); - }, - extendArray: function (sourceArray, targetArray, keyProperty) { - if (!targetArray || !sourceArray || sourceArray.length != targetArray.length) { - return false; - } - - for (var i = 0; i < targetArray.length; i++) { - if (targetArray[i][keyProperty] == sourceArray[i][keyProperty]) { - angular.extend(targetArray[i], sourceArray[i]); - } else { - return false; - } - } - - return true; - }, - copyObjectTo: function (from, to) { - if (!to) { - return from; - } - - for (var name in from) { - if (!from.hasOwnProperty(name)) { - continue; - } - - var fromValue = from[name]; - var toValue = to[name]; - - if (angular.isObject(fromValue) || angular.isArray(fromValue)) { - to[name] = this.copyObjectTo(from[name], to[name]); - } else { - if (fromValue != toValue) { - to[name] = fromValue; - } - } - } - - return to; - }, - getFileNameFromPath: function (path) { - if (!path) { - return path; - } - - var index = path.lastIndexOf('/'); - - if (index <= 0 || index == path.length) { - return path; - } - - return path.substring(index + 1); - }, - isUrlMatchUrl2: function (url, url2) { - if (url === url2) { - return true; - } - - var index = url2.indexOf(url); - - if (index !== 0) { - return false; - } - - var lastPart = url2.substring(url.length); - - if (lastPart.indexOf('/') == 0) { - return true; - } - - return false; - }, - getOptions: function (keys) { - var options = []; - - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - var option = aria2AllOptions[key]; - - if (!option) { - continue; - } - - option = angular.extend({ - key: key, - nameKey: 'options.' + key + '.name', - descriptionKey: 'options.' + key + '.description' - }, option); - - options.push(option); - } - - return options; - }, - getTaskName: function (task) { - var taskName = ""; - - if (task.bittorrent && task.bittorrent.info) { - taskName = task.bittorrent.info.name; - } - - if (!taskName && task.files && task.files.length >= 1) { - taskName = this.getFileNameFromPath(task.files[0].path); - } - - if (!taskName && task.files && task.files.length >= 1 && task.files[0].uris && task.files[0].uris.length >= 1) { - taskName = this.getFileNameFromPath(task.files[0].uris[0].uri); - } - - if (!taskName) { - taskName = $translate.instant('Unknown'); - } - - return taskName; - }, - processDownloadTask: function (task) { - if (!task) { - return task; - } - - task.totalLength = parseInt(task.totalLength); - task.completedLength = parseInt(task.completedLength); - task.uploadSpeed = parseInt(task.uploadSpeed); - task.downloadSpeed = parseInt(task.downloadSpeed); - task.completePercent = (task.totalLength > 0 ? task.completedLength / task.totalLength * 100 : 0); - task.remainPercent = 100 - task.completePercent; - task.taskName = this.getTaskName(task); - task.idle = task.downloadSpeed == 0; - - var remainLength = task.totalLength - task.completedLength; - task.remainTime = calculateDownloadRemainTime(remainLength, task.downloadSpeed); - - if (task.files) { - for (var i = 0; i < task.files.length; i++) { - var file = task.files[i]; - file.fileName = this.getFileNameFromPath(file.path); - file.length = parseInt(file.length); - file.completedLength = parseInt(file.completedLength); - file.completePercent = (file.length > 0 ? file.completedLength / file.length * 100 : 0); - } - } - - return task; - }, - parseOrderType: function (value) { - var values = value.split(':'); - - var obj = { - type: values[0], - order: values[1], - equals: function (obj) { - if (angular.isUndefined(obj.order)) { - return this.type === obj.type; - } else { - return this.type === obj.type && this.order === obj.order; - } - }, - getValue: function () { - return this.type + ":" + this.order; - } - }; - - Object.defineProperty(obj, 'reverse', { - get: function () { - return this.order === 'desc'; - }, - set: function (value) { - this.order = (value ? 'desc' : 'asc'); - } - }); - - return obj; - }, - estimateCompletedPercentFromBitField: function (bitfield) { - var totalLength = bitfield.length * 0xf; - var completedLength = 0; - - if (totalLength == 0) { - return 0; - } - - for (var i = 0; i < bitfield.length; i++) { - var num = parseInt(bitfield[i], 16); - completedLength += num; - } - - return completedLength / totalLength; - }, - estimateHealthPercentFromPeers: function (task, peers) { - if (peers.length < 1) { - return task.completePercent; - } - - var bitfieldCompletedArr = new Array(task.bitfield.length); - var bitfieldPieceArr = new Array(task.bitfield.length); - var totalLength = task.bitfield.length * 0xf; - var healthBitCount = 0; - - for (var i = 0; i < task.bitfield.length; i++) { - var num = parseInt(task.bitfield[i], 16); - bitfieldCompletedArr[i] = 0; - bitfieldPieceArr[i] = 0; - - if (num == 0xf) { - bitfieldCompletedArr[i] = num; - } else { - bitfieldPieceArr[i] = num; - } - } - - for (var i = 0; i < peers.length; i++) { - var peer = peers[i]; - var bitfield = peer.bitfield; - - for (var j = 0; j < bitfield.length; j++) { - var num = parseInt(bitfield[j], 16); - - if (num == 0xf) { - bitfieldCompletedArr[j] += num; - } else { - bitfieldPieceArr[j] = Math.max(bitfieldPieceArr[j], num); - } - } - } - - for (var i = 0; i < bitfieldCompletedArr.length; i++) { - bitfieldCompletedArr[i] += bitfieldPieceArr[i]; - } - - while (true) { - var completed = true; - - for (var i = 0; i < bitfieldCompletedArr.length; i++) { - var bitCount = Math.min(bitfieldCompletedArr[i], 0xf); - healthBitCount += bitCount; - bitfieldCompletedArr[i] -= bitCount; - - if (bitCount < 0xf) { - completed = false; - } - } - - if (!completed) { - break; - } - } - - var healthPercent = healthBitCount / totalLength * 100; - - if (healthPercent < task.completePercent) { - healthPercent = task.completePercent; - } - - return healthPercent; - } - }; - }]); -})(); diff --git a/app/scripts/filters/fileOrderBy.js b/app/scripts/filters/fileOrderBy.js index 034254c..b6782a6 100644 --- a/app/scripts/filters/fileOrderBy.js +++ b/app/scripts/filters/fileOrderBy.js @@ -1,13 +1,13 @@ (function () { 'use strict'; - angular.module("ariaNg").filter('fileOrderBy', ['orderByFilter', 'utils', function (orderByFilter, utils) { + angular.module("ariaNg").filter('fileOrderBy', ['orderByFilter', 'ariaNgCommonService', function (orderByFilter, ariaNgCommonService) { return function (array, type) { if (!angular.isArray(array)) { return array; } - var orderType = utils.parseOrderType(type); + var orderType = ariaNgCommonService.parseOrderType(type); if (orderType == null) { return array; diff --git a/app/scripts/filters/filename.js b/app/scripts/filters/filename.js deleted file mode 100644 index 5d3de08..0000000 --- a/app/scripts/filters/filename.js +++ /dev/null @@ -1,9 +0,0 @@ -(function () { - 'use strict'; - - angular.module("ariaNg").filter('filename', ['utils', function (utils) { - return function (path) { - return utils.getFileNameFromPath(path); - } - }]); -})(); diff --git a/app/scripts/filters/taskOrderBy.js b/app/scripts/filters/taskOrderBy.js index 1517c9b..f2c0d70 100644 --- a/app/scripts/filters/taskOrderBy.js +++ b/app/scripts/filters/taskOrderBy.js @@ -1,13 +1,13 @@ (function () { 'use strict'; - angular.module("ariaNg").filter('taskOrderBy', ['orderByFilter', 'utils', function (orderByFilter, utils) { + angular.module("ariaNg").filter('taskOrderBy', ['orderByFilter', 'ariaNgCommonService', function (orderByFilter, ariaNgCommonService) { return function (array, type) { if (!angular.isArray(array)) { return array; } - var orderType = utils.parseOrderType(type); + var orderType = ariaNgCommonService.parseOrderType(type); if (orderType == null) { return array; diff --git a/app/scripts/services/aria2RpcService.js b/app/scripts/services/aria2RpcService.js index 5690d09..64744c2 100644 --- a/app/scripts/services/aria2RpcService.js +++ b/app/scripts/services/aria2RpcService.js @@ -1,7 +1,7 @@ (function () { 'use strict'; - angular.module('ariaNg').factory('aria2RpcService', ['$q', 'aria2RpcConstants', 'ariaNgSettingService', 'aria2HttpRpcService', 'aria2WebSocketRpcService', 'utils', function ($q, aria2RpcConstants, ariaNgSettingService, aria2HttpRpcService, aria2WebSocketRpcService, utils) { + angular.module('ariaNg').factory('aria2RpcService', ['$q', 'aria2RpcConstants', 'ariaNgCommonService', 'ariaNgSettingService', 'aria2HttpRpcService', 'aria2WebSocketRpcService', function ($q, aria2RpcConstants, ariaNgCommonService, ariaNgSettingService, aria2HttpRpcService, aria2WebSocketRpcService) { var protocol = ariaNgSettingService.getProtocol(); var getAria2MethodFullName = function (methodName) { @@ -9,10 +9,10 @@ }; var invoke = function (method, context) { - context.uniqueId = utils.generateUniqueId(); + context.uniqueId = ariaNgCommonService.generateUniqueId(); context.requestBody = { jsonrpc: aria2RpcConstants.rpcServiceVersion, - method: (method.indexOf('system.') != 0 ? getAria2MethodFullName(method) : method), + method: (method.indexOf(aria2RpcConstants.rpcSystemServiceName + '.') != 0 ? getAria2MethodFullName(method) : method), id: context.uniqueId, params: context.params }; diff --git a/app/scripts/services/aria2SettingService.js b/app/scripts/services/aria2SettingService.js new file mode 100644 index 0000000..1fb0441 --- /dev/null +++ b/app/scripts/services/aria2SettingService.js @@ -0,0 +1,96 @@ +(function () { + 'use strict'; + + angular.module('ariaNg').factory('aria2SettingService', ['aria2AllOptions', 'aria2GlobalAvailableOptions', 'aria2RpcService', function (aria2AllOptions, aria2GlobalAvailableOptions, aria2RpcService) { + var processStatResult = function (stat) { + if (!stat) { + return stat; + } + + var activeCount = parseInt(stat.numActive); + var waitingCount = parseInt(stat.numWaiting); + var totalRunningCount = activeCount + waitingCount; + + stat.totalRunningCount = totalRunningCount; + + return stat; + }; + + return { + getAvailableOptionsKeys: function (type) { + if (type == 'basic') { + return aria2GlobalAvailableOptions.basicOptions; + } else if (type == 'http-ftp-sftp') { + return aria2GlobalAvailableOptions.httpFtpSFtpOptions; + } else if (type == 'http') { + return aria2GlobalAvailableOptions.httpOptions; + } else if (type == 'ftp-sftp') { + return aria2GlobalAvailableOptions.ftpSFtpOptions; + } else if (type == 'bt') { + return aria2GlobalAvailableOptions.btOptions; + } else if (type == 'metalink') { + return aria2GlobalAvailableOptions.metalinkOptions; + } else if (type == 'rpc') { + return aria2GlobalAvailableOptions.rpcOptions; + } else if (type == 'advanced') { + return aria2GlobalAvailableOptions.advancedOptions; + } else { + return false; + } + }, + getSpecifiedOptions: function (keys) { + var options = []; + + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var option = aria2AllOptions[key]; + + if (!option) { + continue; + } + + option = angular.extend({ + key: key, + nameKey: 'options.' + key + '.name', + descriptionKey: 'options.' + key + '.description' + }, option); + + options.push(option); + } + + return options; + }, + getGlobalOption: function (callback) { + return aria2RpcService.getGlobalOption({ + callback: callback + }); + }, + setGlobalOption: function (key, value, callback) { + var data = {}; + data[key] = value; + + return aria2RpcService.changeGlobalOption({ + options: data, + callback: callback + }); + }, + getServerStatus: function (callback) { + return aria2RpcService.getVersion({ + callback: callback + }) + }, + getGlobalStat: function (callback) { + return aria2RpcService.getGlobalStat({ + callback: function (result) { + if (!callback) { + return; + } + + var stat = processStatResult(result); + callback(stat); + } + }); + } + }; + }]); +})(); diff --git a/app/scripts/services/ariaNgCommonService.js b/app/scripts/services/ariaNgCommonService.js new file mode 100644 index 0000000..8547670 --- /dev/null +++ b/app/scripts/services/ariaNgCommonService.js @@ -0,0 +1,116 @@ +(function () { + 'use strict'; + + angular.module('ariaNg').factory('ariaNgCommonService', ['$location', '$timeout', '$base64', 'SweetAlert', '$translate', 'ariaNgConstants', function ($location, $timeout, $base64, SweetAlert, $translate, ariaNgConstants) { + return { + generateUniqueId: function () { + var sourceId = ariaNgConstants.appPrefix + '_' + Math.round(new Date().getTime() / 1000) + '_' + Math.random(); + var hashedId = $base64.encode(sourceId); + + return hashedId; + }, + alert: function (text) { + $timeout(function () { + SweetAlert.swal({ + title: $translate.instant('Error'), + text: $translate.instant(text), + type: 'error', + confirmButtonText: $translate.instant('OK') + }); + }, 100); + }, + confirm: function (title, text, type, callback) { + var options = { + title: $translate.instant(title), + text: $translate.instant(text), + type: type, + showCancelButton: true, + confirmButtonText: $translate.instant('OK'), + cancelButtonText: $translate.instant('Cancel') + }; + + if (type == 'warning') { + options.confirmButtonColor = '#F39C12'; + } + + SweetAlert.swal(options, function (isConfirm) { + if (!isConfirm) { + return; + } + + if (callback) { + callback(); + } + }); + }, + extendArray: function (sourceArray, targetArray, keyProperty) { + if (!targetArray || !sourceArray || sourceArray.length != targetArray.length) { + return false; + } + + for (var i = 0; i < targetArray.length; i++) { + if (targetArray[i][keyProperty] == sourceArray[i][keyProperty]) { + angular.extend(targetArray[i], sourceArray[i]); + } else { + return false; + } + } + + return true; + }, + copyObjectTo: function (from, to) { + if (!to) { + return from; + } + + for (var name in from) { + if (!from.hasOwnProperty(name)) { + continue; + } + + var fromValue = from[name]; + var toValue = to[name]; + + if (angular.isObject(fromValue) || angular.isArray(fromValue)) { + to[name] = this.copyObjectTo(from[name], to[name]); + } else { + if (fromValue != toValue) { + to[name] = fromValue; + } + } + } + + return to; + }, + parseOrderType: function (value) { + var values = value.split(':'); + + var obj = { + type: values[0], + order: values[1], + equals: function (obj) { + if (angular.isUndefined(obj.order)) { + return this.type === obj.type; + } else { + return this.type === obj.type && this.order === obj.order; + } + }, + getValue: function () { + return this.type + ":" + this.order; + } + }; + + Object.defineProperty(obj, 'reverse', { + get: function () { + return this.order === 'desc'; + }, + set: function (value) { + this.order = (value ? 'desc' : 'asc'); + } + }); + + return obj; + } + }; + }]); +})(); diff --git a/app/scripts/services/ariaNgSettingService.js b/app/scripts/services/ariaNgSettingService.js index 78ce311..f778bf4 100644 --- a/app/scripts/services/ariaNgSettingService.js +++ b/app/scripts/services/ariaNgSettingService.js @@ -59,7 +59,7 @@ $translate.use(lang); amMoment.changeLocale(lang); - + return true; }, getLanguage: function () { diff --git a/app/scripts/services/ariaNgTaskService.js b/app/scripts/services/ariaNgTaskService.js new file mode 100644 index 0000000..9f0842d --- /dev/null +++ b/app/scripts/services/ariaNgTaskService.js @@ -0,0 +1,248 @@ +(function () { + 'use strict'; + + angular.module('ariaNg').factory('ariaNgTaskService', ['$translate', 'aria2RpcService', function ($translate, aria2RpcService) { + var getFileNameFromPath = function (path) { + if (!path) { + return path; + } + + var index = path.lastIndexOf('/'); + + if (index <= 0 || index == path.length) { + return path; + } + + return path.substring(index + 1); + }; + + var calculateDownloadRemainTime = function (remainBytes, downloadSpeed) { + if (downloadSpeed == 0) { + return 0; + } + + return remainBytes / downloadSpeed; + }; + + var getTaskName = function (task) { + var taskName = ""; + + if (task.bittorrent && task.bittorrent.info) { + taskName = task.bittorrent.info.name; + } + + if (!taskName && task.files && task.files.length >= 1) { + taskName = getFileNameFromPath(task.files[0].path); + } + + if (!taskName && task.files && task.files.length >= 1 && task.files[0].uris && task.files[0].uris.length >= 1) { + taskName = getFileNameFromPath(task.files[0].uris[0].uri); + } + + if (!taskName) { + taskName = $translate.instant('Unknown'); + } + + return taskName; + }; + + var processDownloadTask = function (task) { + if (!task) { + return task; + } + + task.totalLength = parseInt(task.totalLength); + task.completedLength = parseInt(task.completedLength); + task.uploadSpeed = parseInt(task.uploadSpeed); + task.downloadSpeed = parseInt(task.downloadSpeed); + task.completePercent = (task.totalLength > 0 ? task.completedLength / task.totalLength * 100 : 0); + task.remainPercent = 100 - task.completePercent; + task.taskName = getTaskName(task); + task.idle = task.downloadSpeed == 0; + + var remainLength = task.totalLength - task.completedLength; + task.remainTime = calculateDownloadRemainTime(remainLength, task.downloadSpeed); + + if (task.files) { + for (var i = 0; i < task.files.length; i++) { + var file = task.files[i]; + file.fileName = getFileNameFromPath(file.path); + file.length = parseInt(file.length); + file.completedLength = parseInt(file.completedLength); + file.completePercent = (file.length > 0 ? file.completedLength / file.length * 100 : 0); + } + } + + return task; + }; + + var estimateCompletedPercentFromBitField = function (bitfield) { + var totalLength = bitfield.length * 0xf; + var completedLength = 0; + + if (totalLength == 0) { + return 0; + } + + for (var i = 0; i < bitfield.length; i++) { + var num = parseInt(bitfield[i], 16); + completedLength += num; + } + + return completedLength / totalLength; + }; + + return { + getTaskList: function (type, full, callback) { + var invokeMethod = null; + + if (type == 'downloading') { + invokeMethod = aria2RpcService.tellActive; + } else if (type == 'waiting') { + invokeMethod = aria2RpcService.tellWaiting; + } else if (type == 'stopped') { + invokeMethod = aria2RpcService.tellStopped; + } else { + return; + } + + return invokeMethod({ + requestParams: full ? aria2RpcService.getFullTaskParams() : aria2RpcService.getBasicTaskParams(), + callback: function (result) { + if (!callback) { + return; + } + + callback(result); + } + }); + }, + getTaskStatus: function (gid, callback) { + return aria2RpcService.tellStatus({ + gid: gid, + callback: function (result) { + if (!callback) { + return; + } + + var task = processDownloadTask(result); + callback(task); + } + }); + }, + getTaskOption: function (gid, callback) { + return aria2RpcService.getOption({ + gid: gid, + callback: callback + }); + }, + getBtTaskPeers: function (gid, callback) { + return aria2RpcService.getPeers({ + gid: gid, + callback: function (result) { + if (!callback) { + return; + } + + if (result) { + for (var i = 0; i < result.length; i++) { + var peer = result[i]; + peer.completePercent = estimateCompletedPercentFromBitField(peer.bitfield) * 100; + } + } + + callback(result); + } + }); + }, + startTasks: function (gids, callback) { + return aria2RpcService.unpauseMulti({ + gids: gids, + callback: callback + }); + }, + pauseTasks: function (gids, callback) { + return aria2RpcService.forcePauseMulti({ + gids: gids, + callback: callback + }); + }, + processDownloadTasks: function (tasks) { + if (!angular.isArray(tasks)) { + return; + } + + for (var i = 0; i < tasks.length; i++) { + processDownloadTask(tasks[i]); + } + }, + estimateHealthPercentFromPeers: function (task, peers) { + if (peers.length < 1) { + return task.completePercent; + } + + var bitfieldCompletedArr = new Array(task.bitfield.length); + var bitfieldPieceArr = new Array(task.bitfield.length); + var totalLength = task.bitfield.length * 0xf; + var healthBitCount = 0; + + for (var i = 0; i < task.bitfield.length; i++) { + var num = parseInt(task.bitfield[i], 16); + bitfieldCompletedArr[i] = 0; + bitfieldPieceArr[i] = 0; + + if (num == 0xf) { + bitfieldCompletedArr[i] = num; + } else { + bitfieldPieceArr[i] = num; + } + } + + for (var i = 0; i < peers.length; i++) { + var peer = peers[i]; + var bitfield = peer.bitfield; + + for (var j = 0; j < bitfield.length; j++) { + var num = parseInt(bitfield[j], 16); + + if (num == 0xf) { + bitfieldCompletedArr[j] += num; + } else { + bitfieldPieceArr[j] = Math.max(bitfieldPieceArr[j], num); + } + } + } + + for (var i = 0; i < bitfieldCompletedArr.length; i++) { + bitfieldCompletedArr[i] += bitfieldPieceArr[i]; + } + + while (true) { + var completed = true; + + for (var i = 0; i < bitfieldCompletedArr.length; i++) { + var bitCount = Math.min(bitfieldCompletedArr[i], 0xf); + healthBitCount += bitCount; + bitfieldCompletedArr[i] -= bitCount; + + if (bitCount < 0xf) { + completed = false; + } + } + + if (!completed) { + break; + } + } + + var healthPercent = healthBitCount / totalLength * 100; + + if (healthPercent < task.completePercent) { + healthPercent = task.completePercent; + } + + return healthPercent; + } + }; + }]); +})(); diff --git a/app/views/task-detail.html b/app/views/task-detail.html index c95e893..c1f6894 100644 --- a/app/views/task-detail.html +++ b/app/views/task-detail.html @@ -31,7 +31,7 @@ -
    +
    File Size
    @@ -40,7 +40,7 @@
    -
    +
    Task Status
    @@ -48,7 +48,7 @@
    -
    +
    Error Description
    @@ -56,7 +56,7 @@
    -
    +
    @@ -64,7 +64,7 @@
    -
    +
    Download
    @@ -72,7 +72,7 @@
    -
    +
    Upload
    @@ -80,7 +80,7 @@
    -
    +
    Remain Time
    @@ -88,7 +88,7 @@
    -
    +
    Info Hash
    @@ -96,7 +96,7 @@
    -
    +
    Connections
    @@ -104,7 +104,7 @@
    -
    +
    Download Dir