ariaNgNativeElectronService.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. (function () {
  2. 'use strict';
  3. angular.module('ariaNg').factory('ariaNgNativeElectronService', ['$window', '$q', 'ariaNgLogService', 'ariaNgLocalizationService', function ($window, $q, ariaNgLogService, ariaNgLocalizationService) {
  4. var electron = angular.isFunction(window.nodeRequire) ? nodeRequire('electron') : {};
  5. var ipcRenderer = electron.ipcRenderer || {};
  6. var onMainProcessEvent = function (channel, callback) {
  7. ipcRenderer.on && ipcRenderer.on(channel, callback);
  8. };
  9. var removeMainProcessEvent = function (channel, callback) {
  10. ipcRenderer.removeListener && ipcRenderer.removeListener(channel, callback);
  11. };
  12. var invokeMainProcessMethod = function (channel, ...args) {
  13. ipcRenderer.send && ipcRenderer.send(channel, ...args);
  14. };
  15. var invokeMainProcessMethodSync = function (channel, ...args) {
  16. if (!ipcRenderer.sendSync) {
  17. return null;
  18. }
  19. return ipcRenderer.sendSync(channel, ...args);
  20. };
  21. var invokeMainProcessMethodAsync = function (channel, ...args) {
  22. if (!ipcRenderer.invoke) {
  23. return null;
  24. }
  25. return ipcRenderer.invoke(channel, ...args);
  26. };
  27. onMainProcessEvent('on-main-log-debug', function (event, msg, obj) {
  28. ariaNgLogService.debug(msg, obj);
  29. });
  30. onMainProcessEvent('on-main-log-info', function (event, msg, obj) {
  31. ariaNgLogService.info(msg, obj);
  32. });
  33. onMainProcessEvent('on-main-log-warn', function (event, msg, obj) {
  34. ariaNgLogService.warn(msg, obj);
  35. });
  36. onMainProcessEvent('on-main-log-error', function (event, msg, obj) {
  37. ariaNgLogService.error(msg, obj);
  38. });
  39. invokeMainProcessMethod('on-render-electron-service-inited');
  40. return {
  41. getRuntimeEnvironment: function () {
  42. return invokeMainProcessMethodSync('render-sync-get-runtime-environment');
  43. },
  44. getVersion: function() {
  45. return invokeMainProcessMethodSync('render-sync-get-global-setting', 'version');
  46. },
  47. getAriaNgVersion: function() {
  48. return invokeMainProcessMethodSync('render-sync-get-global-setting', 'ariaNgVersion');
  49. },
  50. getBuildCommit: function () {
  51. return invokeMainProcessMethodSync('render-sync-get-global-setting', 'buildCommit');
  52. },
  53. isDevMode: function () {
  54. return invokeMainProcessMethodSync('render-sync-get-global-setting', 'isDevMode');
  55. },
  56. useCustomAppTitle: function () {
  57. return invokeMainProcessMethodSync('render-sync-get-global-setting', 'useCustomAppTitle');
  58. },
  59. setNativeTheme: function (theme) {
  60. invokeMainProcessMethod('render-set-native-theme', theme);
  61. },
  62. updateTitleBarBackgroundColor: function () {
  63. var titleBar = angular.element('#window-title-bar');
  64. if (!titleBar || !titleBar[0]) {
  65. return;
  66. }
  67. var computedStyle = $window.getComputedStyle(titleBar[0]);
  68. var backgroundColor = computedStyle.getPropertyValue('background-color');
  69. var symbolColor = computedStyle.getPropertyValue('color');
  70. invokeMainProcessMethod('render-set-titlebar-color', backgroundColor, symbolColor);
  71. },
  72. updateTitleBarBackgroundColorWithSweetAlertOverlay: function () {
  73. var titleBar = angular.element('#window-title-bar');
  74. if (!titleBar || !titleBar[0]) {
  75. return;
  76. }
  77. var computedStyle = $window.getComputedStyle(titleBar[0]);
  78. var backgroundColor = computedStyle.getPropertyValue('background-color');
  79. var symbolColor = computedStyle.getPropertyValue('color');
  80. // This electron version not support transparent title bar, so we set hard code color
  81. var currentTheme = angular.element('body').hasClass('theme-dark') ? 'dark' : 'light';
  82. if (currentTheme === 'light') {
  83. backgroundColor = 'rgb(148, 148, 148)';
  84. } else if (currentTheme === 'dark') {
  85. backgroundColor = 'rgb(7, 7, 7)';
  86. }
  87. invokeMainProcessMethod('render-set-titlebar-color', backgroundColor, symbolColor);
  88. },
  89. updateTitleBarBackgroundColorWithModalOverlay: function () {
  90. var titleBar = angular.element('#window-title-bar');
  91. if (!titleBar || !titleBar[0]) {
  92. return;
  93. }
  94. var computedStyle = $window.getComputedStyle(titleBar[0]);
  95. var backgroundColor = computedStyle.getPropertyValue('background-color');
  96. var symbolColor = computedStyle.getPropertyValue('color');
  97. // This electron version not support transparent title bar, so we set hard code color
  98. var currentTheme = angular.element('body').hasClass('theme-dark') ? 'dark' : 'light';
  99. if (currentTheme === 'light') {
  100. backgroundColor = 'rgb(86, 86, 86)';
  101. } else if (currentTheme === 'dark') {
  102. backgroundColor = 'rgb(6, 6, 6)';
  103. }
  104. invokeMainProcessMethod('render-set-titlebar-color', backgroundColor, symbolColor);
  105. },
  106. reload: function () {
  107. invokeMainProcessMethod('render-reload-native-window');
  108. },
  109. showTextboxContextMenu: function (context) {
  110. invokeMainProcessMethod('render-show-textbox-context-menu', context);
  111. },
  112. showSystemNotification: function (context) {
  113. invokeMainProcessMethod('render-show-system-notification', context);
  114. },
  115. setApplicationMenu: function () {
  116. invokeMainProcessMethod('render-update-app-menu-label', {
  117. AboutAriaNgNative: ariaNgLocalizationService.getLocalizedText('menu.AboutAriaNgNative'),
  118. Services: ariaNgLocalizationService.getLocalizedText('menu.Services'),
  119. HideAriaNgNative: ariaNgLocalizationService.getLocalizedText('menu.HideAriaNgNative'),
  120. HideOthers: ariaNgLocalizationService.getLocalizedText('menu.HideOthers'),
  121. ShowAll: ariaNgLocalizationService.getLocalizedText('menu.ShowAll'),
  122. QuitAriaNgNative: ariaNgLocalizationService.getLocalizedText('menu.QuitAriaNgNative'),
  123. Edit: ariaNgLocalizationService.getLocalizedText('menu.Edit'),
  124. Undo: ariaNgLocalizationService.getLocalizedText('menu.Undo'),
  125. Redo: ariaNgLocalizationService.getLocalizedText('menu.Redo'),
  126. Cut: ariaNgLocalizationService.getLocalizedText('menu.Cut'),
  127. Copy: ariaNgLocalizationService.getLocalizedText('menu.Copy'),
  128. Paste: ariaNgLocalizationService.getLocalizedText('menu.Paste'),
  129. Delete: ariaNgLocalizationService.getLocalizedText('menu.Delete'),
  130. SelectAll: ariaNgLocalizationService.getLocalizedText('menu.SelectAll'),
  131. Window: ariaNgLocalizationService.getLocalizedText('menu.Window'),
  132. Minimize: ariaNgLocalizationService.getLocalizedText('menu.Minimize'),
  133. Zoom: ariaNgLocalizationService.getLocalizedText('menu.Zoom'),
  134. BringAllToFront: ariaNgLocalizationService.getLocalizedText('menu.BringAllToFront')
  135. });
  136. },
  137. setTrayMenu: function () {
  138. invokeMainProcessMethod('render-update-tray-menu-label', {
  139. ShowAriaNgNative: ariaNgLocalizationService.getLocalizedText('tray.ShowAriaNgNative'),
  140. Exit: ariaNgLocalizationService.getLocalizedText('tray.Exit')
  141. });
  142. },
  143. setTrayToolTip: function (value) {
  144. invokeMainProcessMethod('render-update-tray-tip', value);
  145. },
  146. setMainWindowLanguage: function () {
  147. this.setApplicationMenu();
  148. this.setTrayMenu();
  149. },
  150. getNativeConfig: function () {
  151. var config = invokeMainProcessMethodSync('render-sync-get-native-config');
  152. var cfg = {};
  153. for (var key in config) {
  154. if (!config.hasOwnProperty(key)) {
  155. continue;
  156. }
  157. cfg[key] = angular.copy(config[key]);
  158. }
  159. return cfg;
  160. },
  161. setDefaultPosition: function (value) {
  162. invokeMainProcessMethod('render-set-native-config-default-position', value);
  163. },
  164. setMinimizedToTray: function (value) {
  165. invokeMainProcessMethod('render-set-native-config-minimized-to-tray', value);
  166. },
  167. setExecCommandOnStartup: function (value) {
  168. invokeMainProcessMethod('render-set-native-config-exec-command-on-startup', value);
  169. },
  170. setExecCommandArgumentsOnStartup: function (value) {
  171. invokeMainProcessMethod('render-set-native-config-exec-command-arguments-on-startup', value);
  172. },
  173. setExecDetachedCommandOnStartup: function (value) {
  174. invokeMainProcessMethod('render-set-native-config-exec-detached-command-on-startup', value);
  175. },
  176. getLastCheckUpdatesTimeAsync: function (callback) {
  177. return invokeMainProcessMethodAsync('render-get-native-config-last-check-updates-time')
  178. .then(function onReceive(lastCheckUpdatesTime) {
  179. if (callback) {
  180. callback(lastCheckUpdatesTime);
  181. }
  182. });
  183. },
  184. setLastCheckUpdatesTime: function (value) {
  185. invokeMainProcessMethod('render-set-native-config-last-check-updates-time', value);
  186. },
  187. getStartupCommandOutputAsync: function () {
  188. return invokeMainProcessMethodAsync('render-get-startup-command-process-output');
  189. },
  190. requestHttp: function (requestContext) {
  191. var deferred = $q.defer();
  192. invokeMainProcessMethodAsync('render-request-http', requestContext)
  193. .then(function onReceive(result) {
  194. if (result && result.success) {
  195. deferred.resolve(result.response);
  196. } else {
  197. deferred.reject(result.response);
  198. }
  199. }).catch(function onError() {
  200. deferred.reject({});
  201. });
  202. return deferred.promise;
  203. },
  204. createWebSocketClient: function (rpcUrl, options) {
  205. var WebSocketClient = function (rpcUrl, options) {
  206. var openCallback = null;
  207. var closeCallback = null;
  208. var messageCallback = null;
  209. Object.defineProperty(WebSocketClient.prototype, 'readyState', {
  210. get: function get() {
  211. return invokeMainProcessMethodSync('render-get-websocket-readystate');
  212. },
  213. set: function set() {
  214. throw new Error('The \"readyState\" property is readonly.');
  215. }
  216. });
  217. this.send = function (request) {
  218. invokeMainProcessMethod('render-send-websocket-message', {
  219. url: rpcUrl,
  220. data: request
  221. });
  222. };
  223. this.reconnect = function () {
  224. invokeMainProcessMethod('render-reconnect-websocket', rpcUrl, options);
  225. };
  226. this.onOpen = function (callback) {
  227. openCallback = callback;
  228. };
  229. this.onClose = function (callback) {
  230. closeCallback = callback;
  231. };
  232. this.onMessage = function (callback) {
  233. messageCallback = callback;
  234. };
  235. onMainProcessEvent('on-main-websocket-open', function (event, e) {
  236. if (e.url !== rpcUrl) {
  237. ariaNgLogService.debug('[ariaNgNativeElectronService.websocket.onOpen] event dropped, because rpc url not equals, excepted url: ' + rpcUrl + ", actual url: " + e.url);
  238. return;
  239. }
  240. if (angular.isFunction(openCallback)) {
  241. openCallback(e);
  242. }
  243. });
  244. onMainProcessEvent('on-main-websocket-close', function (event, e) {
  245. if (e.url !== rpcUrl) {
  246. ariaNgLogService.debug('[ariaNgNativeElectronService.websocket.onClose] event dropped, because rpc url not equals, excepted url: ' + rpcUrl + ", actual url: " + e.url);
  247. return;
  248. }
  249. if (angular.isFunction(closeCallback)) {
  250. closeCallback(e);
  251. }
  252. });
  253. onMainProcessEvent('on-main-websocket-message', function (event, message) {
  254. if (message.url !== rpcUrl) {
  255. ariaNgLogService.debug('[ariaNgNativeElectronService.websocket.onMessage] event dropped, because rpc url not equals, excepted url: ' + rpcUrl + ", actual url: " + message.url, message.data);
  256. return;
  257. }
  258. if (angular.isFunction(messageCallback)) {
  259. messageCallback(message);
  260. }
  261. });
  262. invokeMainProcessMethod('render-connect-websocket', rpcUrl, options);
  263. };
  264. return new WebSocketClient(rpcUrl, options);
  265. },
  266. openProjectLink: function () {
  267. invokeMainProcessMethod('render-open-external-url', 'https://github.com/mayswind/AriaNg-Native');
  268. },
  269. openProjectReleaseLink: function () {
  270. invokeMainProcessMethod('render-open-external-url', 'https://github.com/mayswind/AriaNg-Native/releases');
  271. },
  272. readPackageFile: function (path) {
  273. return invokeMainProcessMethodSync('render-sync-get-package-file-content', path);
  274. },
  275. getLocalFSFileBufferAsync: function (fullpath, callback) {
  276. return invokeMainProcessMethodAsync('render-get-localfs-file-buffer', fullpath)
  277. .then(function onReceive(buffer) {
  278. if (callback) {
  279. callback(buffer);
  280. }
  281. });
  282. },
  283. getLocalFSExistsAsync: function (fullpath, callback) {
  284. return invokeMainProcessMethodAsync('render-get-localfs-exists', fullpath)
  285. .then(function onReceive(exists) {
  286. if (callback) {
  287. callback(exists);
  288. }
  289. });
  290. },
  291. openFileInDirectory: function (dir, filename) {
  292. invokeMainProcessMethod('render-open-local-directory', dir, filename);
  293. },
  294. showOpenFileDialogAsync: function (filters, callback) {
  295. return invokeMainProcessMethodAsync('render-show-open-file-dialog', filters)
  296. .then(function onReceive(result) {
  297. if (callback) {
  298. callback({
  299. canceled: result.canceled,
  300. filePaths: result.filePaths
  301. });
  302. }
  303. });
  304. },
  305. showDevTools: function () {
  306. invokeMainProcessMethod('render-show-dev-tools');
  307. },
  308. parseBittorrentInfo: function (data) {
  309. var info = angular.copy(invokeMainProcessMethodSync('render-sync-parse-bittorrent-info', data));
  310. if (info) {
  311. info.type = 'bittorrent';
  312. ariaNgLogService.debug('[ariaNgNativeElectronService.parseBittorrentInfo] bittorrent info', info);
  313. } else {
  314. ariaNgLogService.debug('[ariaNgNativeElectronService.parseBittorrentInfo] cannot parse bittorrent info', info);
  315. }
  316. return info;
  317. },
  318. notifyMainProcessViewLoaded: function (locationPath) {
  319. invokeMainProcessMethod('on-render-view-content-loaded', locationPath);
  320. },
  321. notifyMainProcessorNewDropFile: function (message) {
  322. invokeMainProcessMethod('on-render-new-drop-file', message);
  323. },
  324. notifyMainProcessorNewDropText: function (message) {
  325. invokeMainProcessMethod('on-render-new-drop-text', message);
  326. },
  327. onMainProcessChangeDevMode: function (callback) {
  328. onMainProcessEvent('on-main-change-dev-mode', callback);
  329. },
  330. onMainProcessShowError: function (callback) {
  331. onMainProcessEvent('on-main-show-error', callback);
  332. },
  333. onMainProcessNavigateTo: function (callback) {
  334. onMainProcessEvent('on-main-navigate-to', callback);
  335. },
  336. onMainProcessNewTaskFromFile: function (callback) {
  337. onMainProcessEvent('on-main-new-task-from-file', callback);
  338. },
  339. onMainProcessNewTaskFromText: function (callback) {
  340. onMainProcessEvent('on-main-new-task-from-text', callback);
  341. },
  342. removeMainProcessNewTaskFromFileCallback: function (callback) {
  343. removeMainProcessEvent('on-main-new-task-from-file', callback);
  344. },
  345. removeMainProcessNewTaskFromTextCallback: function (callback) {
  346. removeMainProcessEvent('on-main-new-task-from-text', callback);
  347. }
  348. };
  349. }]);
  350. }());