diff --git a/src/langs/zh_CN.json b/src/langs/zh_CN.json index 9277d6b..1f4d4f1 100644 --- a/src/langs/zh_CN.json +++ b/src/langs/zh_CN.json @@ -100,7 +100,9 @@ "Your browser does not support loading file!": "您的浏览器不支持加载文件!", "The selected file type is invalid!": "选择的文件类型无效!", "Failed to load file!": "加载文件失败!", - "More Options": "更多选项", + "Download Completed": "下载完成", + "BT Download Completed": "BT 下载完成", + "Download Error": "下载出错", "Language": "语言", "Page Title": "页面标题", "Page Title Refresh Interval": "页面标题刷新间隔", diff --git a/src/scripts/config/defaultLanguage.js b/src/scripts/config/defaultLanguage.js index 8addcaa..a5756c3 100644 --- a/src/scripts/config/defaultLanguage.js +++ b/src/scripts/config/defaultLanguage.js @@ -104,7 +104,9 @@ 'Your browser does not support loading file!': 'Your browser does not support loading file!', 'The selected file type is invalid': 'The selected file type is invalid', 'Failed to load file!': 'Failed to load file!', - 'More Options': 'More Options', + 'Download Completed': 'Download Completed', + 'BT Download Completed': 'BT Download Completed', + 'Download Error': 'Download Error', 'Language': 'Language', 'Page Title': 'Page Title', 'Page Title Refresh Interval': 'Page Title Refresh Interval', diff --git a/src/scripts/core/root.js b/src/scripts/core/root.js index de6d312..0086d8f 100644 --- a/src/scripts/core/root.js +++ b/src/scripts/core/root.js @@ -1,7 +1,7 @@ (function () { 'use strict'; - angular.module('ariaNg').run(['$rootScope', '$location', '$document', 'SweetAlert', function ($rootScope, $location, $document, SweetAlert) { + angular.module('ariaNg').run(['$rootScope', '$location', '$document', 'SweetAlert', 'ariaNgNotificationService', 'aria2TaskService', function ($rootScope, $location, $document, SweetAlert, ariaNgNotificationService, aria2TaskService) { var isUrlMatchUrl2 = function (url, url2) { if (url === url2) { return true; @@ -142,6 +142,18 @@ } }; + aria2TaskService.onTaskCompleted(function (event) { + ariaNgNotificationService.notifyTaskComplete(event.task); + }); + + aria2TaskService.onBtTaskCompleted(function (event) { + ariaNgNotificationService.notifyBtTaskComplete(event.task); + }); + + aria2TaskService.onTaskErrorOccur(function (event) { + ariaNgNotificationService.notifyTaskError(event.task); + }); + $rootScope.$on('$locationChangeStart', function (event) { SweetAlert.close(); diff --git a/src/scripts/services/aria2HttpRpcService.js b/src/scripts/services/aria2HttpRpcService.js index 724d852..f0ea6a5 100644 --- a/src/scripts/services/aria2HttpRpcService.js +++ b/src/scripts/services/aria2HttpRpcService.js @@ -33,6 +33,9 @@ context.errorCallback(data.id, data.error); } }); + }, + on: function (eventName, callback) { + //Not implement } }; }]); diff --git a/src/scripts/services/aria2RpcService.js b/src/scripts/services/aria2RpcService.js index 72c6f5d..4773a5c 100644 --- a/src/scripts/services/aria2RpcService.js +++ b/src/scripts/services/aria2RpcService.js @@ -2,9 +2,16 @@ 'use strict'; angular.module('ariaNg').factory('aria2RpcService', ['$q', 'aria2RpcConstants', 'aria2RpcErrors', 'ariaNgCommonService', 'ariaNgSettingService', 'aria2HttpRpcService', 'aria2WebSocketRpcService', function ($q, aria2RpcConstants, aria2RpcErrors, ariaNgCommonService, ariaNgSettingService, aria2HttpRpcService, aria2WebSocketRpcService) { - var protocol = ariaNgSettingService.getProtocol(); + var rpcImplementService = ariaNgSettingService.isUseWebSocket() ? aria2WebSocketRpcService : aria2HttpRpcService; var secret = ariaNgSettingService.getSecret(); + var onDownloadStartCallbacks = []; + var onDownloadPauseCallbacks = []; + var onDownloadStopCallbacks = []; + var onDownloadCompleteCallbacks = []; + var onDownloadErrorCallbacks = []; + var onBtDownloadCompleteCallbacks = []; + var checkIsSystemMethod = function (methodName) { return methodName.indexOf(aria2RpcConstants.rpcSystemServiceName + '.') == 0; }; @@ -13,6 +20,10 @@ return aria2RpcConstants.rpcServiceName + '.' + methodName; }; + var getAria2EventFullName = function (eventName) { + return getAria2MethodFullName(eventName); + }; + var invoke = function (context) { var uniqueId = ariaNgCommonService.generateUniqueId(); @@ -30,11 +41,22 @@ errorCallback: context.errorCallback }; - if (protocol == 'ws' || protocol == 'wss') { - return aria2WebSocketRpcService.request(requestContext); - } else { - return aria2HttpRpcService.request(requestContext); - } + return rpcImplementService.request(requestContext); + }; + + var registerEvent = function (eventName, callbacks) { + var fullEventName = getAria2EventFullName(eventName); + + rpcImplementService.on(fullEventName, function (context) { + if (!angular.isArray(callbacks) || callbacks.length < 1) { + return; + } + + for (var i = 0; i < callbacks.length; i++) { + var callback = callbacks[i]; + callback(context); + } + }); }; var invokeMulti = function (methodFunc, contexts, callback) { @@ -141,6 +163,15 @@ return context; }; + (function () { + registerEvent('onDownloadStart', onDownloadStartCallbacks); + registerEvent('onDownloadPause', onDownloadPauseCallbacks); + registerEvent('onDownloadStop', onDownloadStopCallbacks); + registerEvent('onDownloadComplete', onDownloadCompleteCallbacks); + registerEvent('onDownloadError', onDownloadErrorCallbacks); + registerEvent('onBtDownloadComplete', onBtDownloadCompleteCallbacks); + })(); + return { getBasicTaskParams: function () { return [ @@ -361,6 +392,24 @@ }, listMethods: function (context) { return invoke(buildRequestContext('system.listMethods', context)); + }, + onDownloadStart: function (context) { + onDownloadStartCallbacks.push(context.callback); + }, + onDownloadPause: function (context) { + onDownloadPauseCallbacks.push(context.callback); + }, + onDownloadStop: function (context) { + onDownloadStopCallbacks.push(context.callback); + }, + onDownloadComplete: function (context) { + onDownloadCompleteCallbacks.push(context.callback); + }, + onDownloadError: function (context) { + onDownloadErrorCallbacks.push(context.callback); + }, + onBtDownloadComplete: function (context) { + onBtDownloadCompleteCallbacks.push(context.callback); } }; }]); diff --git a/src/scripts/services/aria2TaskService.js b/src/scripts/services/aria2TaskService.js index d3089dd..74389b6 100644 --- a/src/scripts/services/aria2TaskService.js +++ b/src/scripts/services/aria2TaskService.js @@ -144,6 +144,24 @@ return combinedPieces; }; + var createEventCallback = function (getTaskStatusFunc, callback, type) { + return function (event) { + var context = { + type: type, + task: null + }; + + if (event && event.gid) { + getTaskStatusFunc(event.gid, function (response) { + context.task = (response.success ? response.data : null); + callback(context); + }, true); + } else { + callback(context); + } + } + }; + var createLocalPeerFromTask = function (task) { return { local: true, @@ -385,6 +403,33 @@ callback: callback }); }, + onTaskCompleted: function (callback) { + if (!callback) { + return; + } + + aria2RpcService.onDownloadComplete({ + callback: createEventCallback(this.getTaskStatus, callback, 'completed') + }); + }, + onBtTaskCompleted: function (callback) { + if (!callback) { + return; + } + + aria2RpcService.onBtDownloadComplete({ + callback: createEventCallback(this.getTaskStatus, callback, 'btcompleted') + }); + }, + onTaskErrorOccur: function (callback) { + if (!callback) { + return; + } + + aria2RpcService.onDownloadError({ + callback: createEventCallback(this.getTaskStatus, callback, 'error') + }); + }, processDownloadTasks: function (tasks) { if (!angular.isArray(tasks)) { return; diff --git a/src/scripts/services/aria2WebSocketRpcService.js b/src/scripts/services/aria2WebSocketRpcService.js index 9145b8d..9cf8adf 100644 --- a/src/scripts/services/aria2WebSocketRpcService.js +++ b/src/scripts/services/aria2WebSocketRpcService.js @@ -4,7 +4,60 @@ angular.module('ariaNg').factory('aria2WebSocketRpcService', ['$q', '$websocket', 'ariaNgSettingService', function ($q, $websocket, ariaNgSettingService) { var rpcUrl = ariaNgSettingService.getJsonRpcUrl(); var socketClient = null; + var sendIdStates = {}; + var eventCallbacks = {}; + + var processMethodCallback = function (content) { + var uniqueId = content.id; + + if (!uniqueId) { + return; + } + + var state = sendIdStates[uniqueId]; + + if (!state) { + return; + } + + var context = state.context; + + state.deferred.resolve({ + success: true, + context: context + }); + + if (content.result && context.successCallback) { + context.successCallback(context.id, content.result); + } + + if (content.error && context.errorCallback) { + context.errorCallback(context.id, content.error); + } + + delete sendIdStates[uniqueId]; + }; + + var processEventCallback = function (content) { + var method = content.method; + + if (!method) { + return; + } + + var callbacks = eventCallbacks[method]; + + if (!angular.isArray(callbacks) || callbacks.length < 1) { + return; + } + + for (var i = 0; i < callbacks.length; i++) { + var callback = callbacks[i]; + var context = (angular.isArray(content.params) && content.params.length > 0 ? content.params[0] : null); + callback(context); + } + }; var getSocketClient = function () { if (socketClient == null) { @@ -17,38 +70,15 @@ var content = angular.fromJson(message.data); - if (!content || !content.id) { + if (!content) { return; } - var uniqueId = content.id; - - if (!sendIdStates[uniqueId]) { - return; + if (content.id) { + processMethodCallback(content); + } else if (content.method) { + processEventCallback(content); } - - var state = sendIdStates[uniqueId]; - - if (!state) { - return; - } - - var context = state.context; - - state.deferred.resolve({ - success: true, - context: context - }); - - if (content.result && context.successCallback) { - context.successCallback(context.id, content.result); - } - - if (content.error && context.errorCallback) { - context.errorCallback(context.id, content.error); - } - - delete sendIdStates[uniqueId]; }); } @@ -75,6 +105,15 @@ client.send(requestBody); return deferred.promise; + }, + on: function (eventName, callback) { + var callbacks = eventCallbacks[eventName]; + + if (!angular.isArray(callbacks)) { + callbacks = eventCallbacks[eventName] = []; + } + + callbacks.push(callback); } }; }]); diff --git a/src/scripts/services/ariaNgNotificationService.js b/src/scripts/services/ariaNgNotificationService.js index 0162c6a..7e463e0 100644 --- a/src/scripts/services/ariaNgNotificationService.js +++ b/src/scripts/services/ariaNgNotificationService.js @@ -1,7 +1,7 @@ (function () { 'use strict'; - angular.module('ariaNg').factory('ariaNgNotificationService', ['$notification', 'ariaNgSettingService', function ($notification, ariaNgSettingService) { + angular.module('ariaNg').factory('ariaNgNotificationService', ['$notification', '$translate', 'ariaNgSettingService', function ($notification, $translate, ariaNgSettingService) { var isSupportBrowserNotification = $notification.isSupported; var isPermissionGranted = function (permission) { @@ -39,10 +39,19 @@ }, notify: function (title, content) { if (isSupportBrowserNotification && ariaNgSettingService.getBrowserNotification()) { - $notification(title, { - body: content + $notification($translate.instant(title), { + body: $translate.instant(content) }); } + }, + notifyTaskComplete: function (task) { + this.notify('Download Completed', (task && task.taskName ? task.taskName : '')); + }, + notifyBtTaskComplete: function (task) { + this.notify('BT Download Completed', (task && task.taskName ? task.taskName : '')); + }, + notifyTaskError: function (task) { + this.notify('Download Error', (task && task.taskName ? task.taskName : '')); } } }]); diff --git a/src/scripts/services/ariaNgSettingService.js b/src/scripts/services/ariaNgSettingService.js index c925ee1..f05f3a1 100644 --- a/src/scripts/services/ariaNgSettingService.js +++ b/src/scripts/services/ariaNgSettingService.js @@ -132,6 +132,10 @@ setProtocol: function (value) { setOption('protocol', value); }, + isUseWebSocket: function () { + var protocol = this.getProtocol(); + return protocol == 'ws' || protocol == 'wss'; + }, getSecret: function () { var value = getOption('secret'); return (value ? base64.decode(value) : value);