root.js 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. (function () {
  2. 'use strict';
  3. angular.module('ariaNg').run(['$window', '$rootScope', '$location', '$document', '$timeout', 'ariaNgSupportedAudioFileTypes', 'ariaNgCommonService', 'ariaNgKeyboardService', 'ariaNgNotificationService', 'ariaNgLogService', 'ariaNgLocalizationService', 'ariaNgSettingService', 'aria2TaskService', 'ariaNgNativeElectronService', 'ariaNgVersionService', function ($window, $rootScope, $location, $document, $timeout, ariaNgSupportedAudioFileTypes, ariaNgCommonService, ariaNgKeyboardService, ariaNgNotificationService, ariaNgLogService, ariaNgLocalizationService, ariaNgSettingService, aria2TaskService, ariaNgNativeElectronService, ariaNgVersionService) {
  4. var autoRefreshAfterPageLoad = false;
  5. var isAnyTextboxOrTextareaFocus = function () {
  6. return angular.element('input[type="text"],textarea').is(':focus');
  7. };
  8. var isUrlMatchUrl2 = function (url, url2) {
  9. if (url === url2) {
  10. return true;
  11. }
  12. var index = url2.indexOf(url);
  13. if (index !== 0) {
  14. return false;
  15. }
  16. var lastPart = url2.substring(url.length);
  17. if (lastPart.indexOf('/') === 0) {
  18. return true;
  19. }
  20. return false;
  21. };
  22. var setLightTheme = function () {
  23. $rootScope.currentTheme = 'light';
  24. angular.element('body').removeClass('theme-dark');
  25. ariaNgNativeElectronService.updateTitleBarBackgroundColor();
  26. };
  27. var setDarkTheme = function () {
  28. $rootScope.currentTheme = 'dark';
  29. angular.element('body').addClass('theme-dark');
  30. ariaNgNativeElectronService.updateTitleBarBackgroundColor();
  31. };
  32. var setThemeBySystemSettings = function () {
  33. if (!ariaNgSettingService.isBrowserSupportDarkMode()) {
  34. setLightTheme();
  35. return;
  36. }
  37. var matchPreferColorScheme = $window.matchMedia('(prefers-color-scheme: dark)');
  38. ariaNgLogService.info('[root.setThemeBySystemSettings] system uses ' + (matchPreferColorScheme.matches ? 'dark' : 'light') + ' theme');
  39. if (matchPreferColorScheme.matches) {
  40. setDarkTheme();
  41. } else {
  42. setLightTheme();
  43. }
  44. };
  45. var initTheme = function () {
  46. if (ariaNgSettingService.getTheme() === 'system') {
  47. ariaNgNativeElectronService.setNativeTheme('system');
  48. setThemeBySystemSettings();
  49. } else if (ariaNgSettingService.getTheme() === 'dark') {
  50. ariaNgNativeElectronService.setNativeTheme('dark');
  51. setDarkTheme();
  52. } else {
  53. ariaNgNativeElectronService.setNativeTheme('light');
  54. setLightTheme();
  55. }
  56. };
  57. var initCheck = function () {
  58. var browserFeatures = ariaNgSettingService.getBrowserFeatures();
  59. if (!browserFeatures.localStroage) {
  60. ariaNgLogService.warn('[root.initCheck] LocalStorage is not supported!');
  61. }
  62. if (!browserFeatures.cookies) {
  63. ariaNgLogService.warn('[root.initCheck] Cookies is not supported!');
  64. }
  65. if (!ariaNgSettingService.isBrowserSupportStorage()) {
  66. angular.element('body').prepend('<div class="disable-overlay"></div>');
  67. angular.element('.main-sidebar').addClass('blur');
  68. angular.element('.navbar').addClass('blur');
  69. angular.element('.content-body').addClass('blur');
  70. ariaNgNotificationService.notifyInPage('', 'You cannot use AriaNg because this browser does not meet the minimum requirements for data storage.', {
  71. type: 'error',
  72. delay: false
  73. });
  74. throw new Error('You cannot use AriaNg because this browser does not meet the minimum requirements for data storage.');
  75. }
  76. };
  77. var initNavbar = function () {
  78. angular.element('section.sidebar > ul > li[data-href-match] > a').click(function () {
  79. angular.element('section.sidebar > ul li').removeClass('active');
  80. angular.element(this).parent().addClass('active');
  81. });
  82. angular.element('section.sidebar > ul > li.treeview > ul.treeview-menu > li[data-href-match] > a').click(function () {
  83. angular.element('section.sidebar > ul li').removeClass('active');
  84. angular.element(this).parent().addClass('active').parent().parent().addClass('active');
  85. });
  86. };
  87. var setNavbarSelected = function (location) {
  88. angular.element('section.sidebar > ul li').removeClass('active');
  89. angular.element('section.sidebar > ul > li[data-href-match]').each(function (index, element) {
  90. var match = angular.element(element).attr('data-href-match');
  91. if (isUrlMatchUrl2(match, location)) {
  92. angular.element(element).addClass('active');
  93. }
  94. });
  95. angular.element('section.sidebar > ul > li.treeview > ul.treeview-menu > li[data-href-match]').each(function (index, element) {
  96. var match = angular.element(element).attr('data-href-match');
  97. if (isUrlMatchUrl2(match, location)) {
  98. angular.element(element).addClass('active').parent().parent().addClass('active');
  99. }
  100. });
  101. };
  102. var initContentWrapper = function () {
  103. //copy from AdminLTE app.js
  104. var defaultNavbarWithAppTitleHeight = 74; // defined in "min-height" of ".custom-app-title .main-header .navbar" in app-title.css
  105. var defaultNavbarHeight = 50; // defined in "min-height" of ".main-header .navbar" in AdminLTE.css
  106. var defaultFooterHeight = 1 + 15 + 15 + 17; // defined in "border-top" of ".main-footer" in AdminLTE.css, "padding" of ".main-footer" in AdminLTE.css and "line-height" of ".skin-aria-ng .main-footer > .navbar > .navbar-toolbar > .nav > li > a" in default.css;
  107. var windowHeight = $(window).height();
  108. var headerHeight = $('.main-header').outerHeight() || (ariaNgNativeElectronService.useCustomAppTitle() ? defaultNavbarWithAppTitleHeight : defaultNavbarHeight);
  109. var footerHeight = $('.main-footer').outerHeight() || defaultFooterHeight;
  110. var neg = headerHeight + footerHeight;
  111. $('.content-wrapper').css('min-height', windowHeight - footerHeight);
  112. $('.content-body').css('height', windowHeight - neg);
  113. };
  114. var initFileDragSupport = function () {
  115. var getDropFile = function (e) {
  116. if (!e || !e.dataTransfer) {
  117. return null;
  118. }
  119. if (e.dataTransfer.items && e.dataTransfer.items[0] && e.dataTransfer.items[0].kind === 'file') {
  120. return e.dataTransfer.items[0].getAsFile();
  121. } else if (e.dataTransfer.files && e.dataTransfer.files[0]) {
  122. return e.dataTransfer.files[0];
  123. } else {
  124. return null;
  125. }
  126. };
  127. var getDropText = function (e) {
  128. if (!e || !e.dataTransfer) {
  129. return null;
  130. }
  131. return e.dataTransfer.getData('text');
  132. };
  133. var dropzone = angular.element('#dropzone');
  134. var dropzoneFileZone = angular.element('#dropzone-filezone');
  135. angular.element($window).on('dragenter', function (e) {
  136. ariaNgCommonService.closeAllDialogs();
  137. dropzone.show();
  138. e.preventDefault();
  139. });
  140. dropzoneFileZone.on('drag dragstart dragend dragover dragenter dragleave drop', function(e) {
  141. e.preventDefault();
  142. e.stopPropagation();
  143. }).on('dragleave dragend drop', function() {
  144. dropzone.hide();
  145. }).on('drop', function(e) {
  146. var file = getDropFile(e.originalEvent);
  147. if (file) {
  148. ariaNgNativeElectronService.notifyMainProcessorNewDropFile({
  149. filePath: file.path,
  150. location: $location.url()
  151. });
  152. return;
  153. }
  154. var text = getDropText(e.originalEvent);
  155. if (text) {
  156. ariaNgNativeElectronService.notifyMainProcessorNewDropText({
  157. text: text,
  158. location: $location.url()
  159. });
  160. }
  161. });
  162. };
  163. var showSidebar = function () {
  164. angular.element('body').removeClass('sidebar-collapse').addClass('sidebar-open');
  165. };
  166. var hideSidebar = function () {
  167. angular.element('body').addClass('sidebar-collapse').removeClass('sidebar-open');
  168. };
  169. var isSidebarShowInSmallScreen = function () {
  170. return angular.element('body').hasClass('sidebar-open');
  171. };
  172. var autoCheckUpdates = function () {
  173. ariaNgVersionService.getTheLatestVersion()
  174. .then(function onSuccess(response) {
  175. ariaNgLogService.debug('[root.autoCheckUpdates] latest version info', response);
  176. if (!response || !response.data || !response.data.tag_name) {
  177. return;
  178. }
  179. var latestVersion = response.data.tag_name;
  180. if (ariaNgVersionService.compareVersion(ariaNgVersionService.getBuildVersionNumber(), latestVersion) < 0) {
  181. if (ariaNgSettingService.getBrowserNotification()) {
  182. ariaNgNotificationService.notifyViaBrowser('AriaNg Native Updates', 'A new version has been released', {
  183. contentParams: {
  184. version: latestVersion
  185. }
  186. });
  187. } else {
  188. ariaNgNotificationService.notifyInPage('', 'A new version has been released', {
  189. delay: false,
  190. type: 'info',
  191. contentParams: {
  192. version: latestVersion
  193. }
  194. });
  195. }
  196. }
  197. }).catch(function onError(response) {
  198. ariaNgLogService.error('[root.autoCheckUpdates] failed to get latest version', response);
  199. });
  200. };
  201. var playSoundAfterDownloadFinished = function () {
  202. if (!ariaNgSettingService.getPlaySoundAfterDownloadFinished()) {
  203. return;
  204. }
  205. if ($rootScope.soundContext.isPlaying()) {
  206. ariaNgLogService.debug('[root.playSoundAfterDownloadFinished] background audio is already playing');
  207. return;
  208. }
  209. $rootScope.soundContext.playSound(ariaNgSettingService.getPlaySoundAfterDownloadFinished(), true);
  210. };
  211. $rootScope.currentTheme = 'light';
  212. $rootScope.searchContext = {
  213. text: '',
  214. setSearchBoxFocused: function () {
  215. angular.element('#search-box').focus();
  216. }
  217. };
  218. $rootScope.taskContext = {
  219. rpcStatus: 'Connecting',
  220. list: [],
  221. selected: {},
  222. enableSelectAll: false,
  223. getSelectedTaskIds: function () {
  224. var result = [];
  225. if (!this.list || !this.selected || this.list.length < 1) {
  226. return result;
  227. }
  228. for (var i = 0; i < this.list.length; i++) {
  229. var task = this.list[i];
  230. if (this.selected[task.gid]) {
  231. result.push(task.gid);
  232. }
  233. }
  234. return result;
  235. },
  236. getSelectedTasks: function () {
  237. var result = [];
  238. if (!this.list || !this.selected || this.list.length < 1) {
  239. return result;
  240. }
  241. for (var i = 0; i < this.list.length; i++) {
  242. var task = this.list[i];
  243. if (this.selected[task.gid]) {
  244. result.push(task);
  245. }
  246. }
  247. return result;
  248. },
  249. isAllSelected: function () {
  250. var isAllSelected = true;
  251. for (var i = 0; i < this.list.length; i++) {
  252. var task = this.list[i];
  253. if (!$rootScope.filterTask(task)) {
  254. continue;
  255. }
  256. if (!this.selected[task.gid]) {
  257. isAllSelected = false;
  258. break;
  259. }
  260. }
  261. return isAllSelected;
  262. },
  263. hasRetryableTask: function () {
  264. for (var i = 0; i < this.list.length; i++) {
  265. var task = this.list[i];
  266. if (!$rootScope.filterTask(task)) {
  267. continue;
  268. }
  269. if ($rootScope.isTaskRetryable(task)) {
  270. return true;
  271. }
  272. }
  273. return false;
  274. },
  275. hasCompletedTask: function () {
  276. for (var i = 0; i < this.list.length; i++) {
  277. var task = this.list[i];
  278. if (!$rootScope.filterTask(task)) {
  279. continue;
  280. }
  281. if (task.status === 'complete') {
  282. return true;
  283. }
  284. }
  285. return false;
  286. },
  287. selectAll: function () {
  288. if (!this.list || !this.selected || this.list.length < 1) {
  289. return;
  290. }
  291. if (!this.enableSelectAll) {
  292. return;
  293. }
  294. var isAllSelected = this.isAllSelected();
  295. for (var i = 0; i < this.list.length; i++) {
  296. var task = this.list[i];
  297. if (!$rootScope.filterTask(task)) {
  298. continue;
  299. }
  300. this.selected[task.gid] = !isAllSelected;
  301. }
  302. },
  303. selectAllFailed: function () {
  304. if (!this.list || !this.selected || this.list.length < 1) {
  305. return;
  306. }
  307. if (!this.enableSelectAll) {
  308. return;
  309. }
  310. var isAllFailedSelected = true;
  311. for (var i = 0; i < this.list.length; i++) {
  312. var task = this.list[i];
  313. if (!$rootScope.filterTask(task)) {
  314. continue;
  315. }
  316. if (!$rootScope.isTaskRetryable(task)) {
  317. continue;
  318. }
  319. if (!this.selected[task.gid]) {
  320. isAllFailedSelected = false;
  321. }
  322. }
  323. for (var i = 0; i < this.list.length; i++) {
  324. var task = this.list[i];
  325. if (!$rootScope.filterTask(task)) {
  326. continue;
  327. }
  328. if (!$rootScope.isTaskRetryable(task)) {
  329. this.selected[task.gid] = false;
  330. continue;
  331. }
  332. this.selected[task.gid] = !isAllFailedSelected;
  333. }
  334. },
  335. selectAllCompleted: function () {
  336. if (!this.list || !this.selected || this.list.length < 1) {
  337. return;
  338. }
  339. if (!this.enableSelectAll) {
  340. return;
  341. }
  342. var isAllFailedSelected = true;
  343. for (var i = 0; i < this.list.length; i++) {
  344. var task = this.list[i];
  345. if (!$rootScope.filterTask(task)) {
  346. continue;
  347. }
  348. if (task.status !== 'complete') {
  349. continue;
  350. }
  351. if (!this.selected[task.gid]) {
  352. isAllFailedSelected = false;
  353. }
  354. }
  355. for (var i = 0; i < this.list.length; i++) {
  356. var task = this.list[i];
  357. if (!$rootScope.filterTask(task)) {
  358. continue;
  359. }
  360. if (task.status !== 'complete') {
  361. this.selected[task.gid] = false;
  362. continue;
  363. }
  364. this.selected[task.gid] = !isAllFailedSelected;
  365. }
  366. }
  367. };
  368. $rootScope.soundContext = {
  369. currentSoundFile: '',
  370. loadSoundFile: function (filePath, callback, silent) {
  371. var player = angular.element('#background-audio')[0];
  372. if (filePath) {
  373. ariaNgNativeElectronService.getLocalFSFileBufferAsync(filePath, function (buffer) {
  374. if (buffer) {
  375. var soundExtension = ariaNgCommonService.getFileExtension(filePath);
  376. var mimeType = ariaNgSupportedAudioFileTypes[soundExtension];
  377. var blob = new Blob([buffer], { type: mimeType });
  378. player.src = URL.createObjectURL(blob);
  379. $rootScope.soundContext.currentSoundFile = filePath;
  380. ariaNgLogService.debug('[root.soundContext.loadSoundFile] background audio is set to ' + filePath);
  381. if (angular.isFunction(callback)) {
  382. callback(filePath);
  383. }
  384. } else {
  385. player.src = '';
  386. $rootScope.soundContext.currentSoundFile = '';
  387. ariaNgLogService.warn('[root.soundContext.loadSoundFile] background audio is set to empty due to the file buffer is null');
  388. if (!silent) {
  389. ariaNgCommonService.showError('Sound file not exists.');
  390. }
  391. }
  392. });
  393. } else {
  394. player.src = '';
  395. $rootScope.soundContext.currentSoundFile = '';
  396. ariaNgLogService.debug('[root.soundContext.loadSoundFile] background audio is set to empty');
  397. }
  398. },
  399. isPlaying: function () {
  400. var player = angular.element('#background-audio')[0];
  401. return !player.paused;
  402. },
  403. playSound: function (filePath, silent) {
  404. if (!filePath) {
  405. return;
  406. }
  407. var player = angular.element('#background-audio')[0];
  408. player.pause();
  409. player.volume = 1.0;
  410. if (this.currentSoundFile !== filePath) {
  411. this.loadSoundFile(filePath, function () {
  412. player.currentTime = 0;
  413. player.play().catch(function (error) {
  414. ariaNgLogService.error('[root.soundContext.playSound] cannot play sound, because ' + error);
  415. if (!silent) {
  416. ariaNgCommonService.showError('Cannot play this sound file.');
  417. }
  418. });
  419. }, !!silent);
  420. } else {
  421. player.currentTime = 0;
  422. player.play().catch(function (error) {
  423. ariaNgLogService.error('[root.soundContext.playSound] cannot play sound, because ' + error);
  424. if (!silent) {
  425. ariaNgCommonService.showError('Cannot play this sound file.');
  426. }
  427. });
  428. }
  429. },
  430. stopPlayingSound: function () {
  431. var player = angular.element('#background-audio')[0];
  432. player.pause();
  433. player.currentTime = 0;
  434. }
  435. };
  436. $rootScope.filterTask = function (task) {
  437. if (!task || !angular.isString(task.taskName)) {
  438. return false;
  439. }
  440. if (!$rootScope.searchContext || !$rootScope.searchContext.text) {
  441. return true;
  442. }
  443. return (task.taskName.toLowerCase().indexOf($rootScope.searchContext.text.toLowerCase()) >= 0);
  444. };
  445. $rootScope.isTaskRetryable = function (task) {
  446. return task && task.status === 'error' && task.errorDescription && !task.bittorrent;
  447. };
  448. $rootScope.keydownActions = {
  449. find: function (event) {
  450. if (event.preventDefault) {
  451. event.preventDefault();
  452. }
  453. $rootScope.searchContext.setSearchBoxFocused();
  454. return false;
  455. }
  456. };
  457. $rootScope.swipeActions = {
  458. leftSwipe: function () {
  459. if (!ariaNgSettingService.getSwipeGesture()) {
  460. return;
  461. }
  462. if (isSidebarShowInSmallScreen()) {
  463. hideSidebar();
  464. return;
  465. }
  466. if (!this.extendLeftSwipe ||
  467. (angular.isFunction(this.extendLeftSwipe) && !this.extendLeftSwipe())) {
  468. hideSidebar();
  469. }
  470. },
  471. rightSwipe: function () {
  472. if (!ariaNgSettingService.getSwipeGesture()) {
  473. return;
  474. }
  475. if (!this.extendRightSwipe ||
  476. (angular.isFunction(this.extendRightSwipe) && !this.extendRightSwipe())) {
  477. showSidebar();
  478. }
  479. }
  480. };
  481. $rootScope.refreshPage = function () {
  482. $window.location.reload();
  483. };
  484. $rootScope.setAutoRefreshAfterPageLoad = function () {
  485. autoRefreshAfterPageLoad = true;
  486. };
  487. $rootScope.setTheme = function (theme) {
  488. if (theme === 'system') {
  489. ariaNgNativeElectronService.setNativeTheme('system');
  490. setThemeBySystemSettings();
  491. } else if (theme === 'dark') {
  492. ariaNgNativeElectronService.setNativeTheme('dark');
  493. setDarkTheme();
  494. } else {
  495. ariaNgNativeElectronService.setNativeTheme('light');
  496. setLightTheme();
  497. }
  498. };
  499. $rootScope.useCustomAppTitle = ariaNgNativeElectronService.useCustomAppTitle();
  500. $window.addEventListener('contextmenu', function (event) {
  501. event.preventDefault();
  502. event.stopPropagation();
  503. var context = {};
  504. if (angular.isFunction($window.getSelection)) {
  505. var selection = $window.getSelection().toString();
  506. context.selected = !!selection && selection.length > 0;
  507. }
  508. if (angular.element(event.target).attr('readonly') === 'readonly') {
  509. context.editable = false;
  510. }
  511. if (angular.element(event.target).attr('data-support-force-delete-empty') === 'true'
  512. && angular.element(event.target).val() === '') {
  513. context.forceDeleteEmpty = true;
  514. }
  515. if (event.target.nodeName.match(/^(input|textarea)$/i) || event.target.isContentEditable) {
  516. ariaNgNativeElectronService.showTextboxContextMenu(context);
  517. }
  518. });
  519. $window.addEventListener('keydown', function (event) {
  520. if (!ariaNgSettingService.getKeyboardShortcuts()) {
  521. return;
  522. }
  523. var isTextboxOrTextareaFocus = isAnyTextboxOrTextareaFocus();
  524. if (ariaNgKeyboardService.isCtrlAPressed(event) && !isTextboxOrTextareaFocus) {
  525. if (angular.isFunction($rootScope.keydownActions.selectAll)) {
  526. return $rootScope.keydownActions.selectAll(event);
  527. }
  528. } else if (ariaNgKeyboardService.isCtrlFPressed(event)) {
  529. if (angular.isFunction($rootScope.keydownActions.find)) {
  530. return $rootScope.keydownActions.find(event);
  531. }
  532. } else if (ariaNgKeyboardService.isDeletePressed(event) && !isTextboxOrTextareaFocus) {
  533. if (angular.isFunction($rootScope.keydownActions.delete)) {
  534. return $rootScope.keydownActions.delete(event);
  535. }
  536. } else if (ariaNgKeyboardService.isCtrlNPressed(event)) {
  537. $rootScope.$apply(function () {
  538. $location.path('/new');
  539. });
  540. }
  541. }, true);
  542. ariaNgNativeElectronService.onMainProcessNavigateTo(function (event, routeUrl) {
  543. angular.element('.modal.in:visible').modal('hide');
  544. angular.element('.modal-backdrop').remove();
  545. $rootScope.$apply(function () {
  546. $location.path(routeUrl);
  547. });
  548. });
  549. ariaNgNativeElectronService.onMainProcessShowError(function (event, message) {
  550. ariaNgCommonService.showError(message);
  551. });
  552. ariaNgNativeElectronService.onMainProcessChangeDevMode(function (event, devMode) {
  553. $rootScope.$apply(function () {
  554. ariaNgSettingService.setDebugMode(devMode);
  555. });
  556. });
  557. ariaNgSettingService.setDebugMode(ariaNgNativeElectronService.isDevMode());
  558. ariaNgSettingService.onFirstAccess(function () {
  559. ariaNgNotificationService.notifyInPage('', 'Tap to configure and get started with AriaNg.', {
  560. delay: false,
  561. onClose: function () {
  562. $location.path('/settings/ariang');
  563. }
  564. });
  565. });
  566. aria2TaskService.onFirstSuccess(function (event) {
  567. ariaNgNotificationService.notifyInPage('', 'is connected', {
  568. type: 'success',
  569. contentPrefix: event.rpcName + ' '
  570. });
  571. });
  572. aria2TaskService.onConnectionSuccess(function () {
  573. $timeout(function () {
  574. if ($rootScope.taskContext.rpcStatus !== 'Connected') {
  575. $rootScope.taskContext.rpcStatus = 'Connected';
  576. }
  577. });
  578. });
  579. aria2TaskService.onConnectionFailed(function () {
  580. $timeout(function () {
  581. if ($rootScope.taskContext.rpcStatus !== 'Disconnected') {
  582. $rootScope.taskContext.rpcStatus = 'Disconnected';
  583. }
  584. });
  585. });
  586. aria2TaskService.onConnectionReconnecting(function () {
  587. $timeout(function () {
  588. if ($rootScope.taskContext.rpcStatus !== 'Reconnecting') {
  589. $rootScope.taskContext.rpcStatus = 'Reconnecting';
  590. }
  591. });
  592. });
  593. aria2TaskService.onConnectionWaitingToReconnect(function () {
  594. $timeout(function () {
  595. if ($rootScope.taskContext.rpcStatus !== 'Waiting to reconnect') {
  596. $rootScope.taskContext.rpcStatus = 'Waiting to reconnect';
  597. }
  598. });
  599. });
  600. aria2TaskService.onTaskCompleted(function (event) {
  601. playSoundAfterDownloadFinished(event.task);
  602. ariaNgNotificationService.notifyTaskComplete(event.task);
  603. });
  604. aria2TaskService.onBtTaskCompleted(function (event) {
  605. playSoundAfterDownloadFinished(event.task);
  606. ariaNgNotificationService.notifyBtTaskComplete(event.task);
  607. });
  608. aria2TaskService.onTaskErrorOccur(function (event) {
  609. playSoundAfterDownloadFinished(event.task);
  610. ariaNgNotificationService.notifyTaskError(event.task);
  611. });
  612. $rootScope.$on('$locationChangeStart', function (event) {
  613. ariaNgCommonService.closeAllDialogs();
  614. $rootScope.loadPromise = null;
  615. delete $rootScope.keydownActions.selectAll;
  616. delete $rootScope.keydownActions.delete;
  617. delete $rootScope.swipeActions.extendLeftSwipe;
  618. delete $rootScope.swipeActions.extendRightSwipe;
  619. if (angular.isArray($rootScope.taskContext.list) && $rootScope.taskContext.list.length > 0) {
  620. $rootScope.taskContext.list.length = 0;
  621. }
  622. if (angular.isObject($rootScope.taskContext.selected)) {
  623. $rootScope.taskContext.selected = {};
  624. }
  625. $rootScope.taskContext.enableSelectAll = false;
  626. });
  627. $rootScope.$on('$routeChangeStart', function (event, next, current) {
  628. var location = $location.path();
  629. setNavbarSelected(location);
  630. $document.unbind('keypress');
  631. });
  632. $rootScope.$on('$viewContentLoaded', function () {
  633. ariaNgNativeElectronService.notifyMainProcessViewLoaded($location.path());
  634. });
  635. $rootScope.$on('$translateChangeSuccess', function(event, current, previous) {
  636. ariaNgNativeElectronService.setMainWindowLanguage();
  637. });
  638. if (ariaNgSettingService.isBrowserSupportDarkMode()) {
  639. var matchPreferColorScheme = $window.matchMedia('(prefers-color-scheme: dark)');
  640. matchPreferColorScheme.addEventListener('change', function (e) {
  641. ariaNgLogService.info('[root] system switches to ' + (e.matches ? 'dark' : 'light') + ' theme');
  642. if (ariaNgSettingService.getTheme() === 'system') {
  643. if (e.matches) {
  644. setDarkTheme();
  645. } else {
  646. setLightTheme();
  647. }
  648. }
  649. });
  650. }
  651. if (ariaNgSettingService.getAutoCheckUpdates() && ariaNgSettingService.getAutoCheckUpdates() !== 'never') {
  652. ariaNgNativeElectronService.getLastCheckUpdatesTimeAsync(function (lastCheckUpdatesTime) {
  653. var checkFrequency = ariaNgSettingService.getAutoCheckUpdates();
  654. var currentTime = parseInt(ariaNgCommonService.getCurrentUnixTime());
  655. var oneDaySeconds = 86400; // s
  656. var needCheckUpdates = false;
  657. if (!angular.isNumber(lastCheckUpdatesTime)) {
  658. needCheckUpdates = true;
  659. } else if (checkFrequency === 'daily' && (currentTime - lastCheckUpdatesTime) >= oneDaySeconds) {
  660. needCheckUpdates = true;
  661. } else if (checkFrequency === 'weekly' && (currentTime - lastCheckUpdatesTime) >= oneDaySeconds * 7) {
  662. needCheckUpdates = true;
  663. } else if (checkFrequency === 'monthly' && (currentTime - lastCheckUpdatesTime) >= oneDaySeconds * 31) {
  664. needCheckUpdates = true;
  665. }
  666. if (needCheckUpdates) {
  667. ariaNgLogService.debug('[root] need check for updates, last check time is ' + lastCheckUpdatesTime);
  668. autoCheckUpdates();
  669. ariaNgNativeElectronService.setLastCheckUpdatesTime(currentTime);
  670. } else {
  671. ariaNgLogService.debug('[root] do not need check for updates, last check time is ' + lastCheckUpdatesTime);
  672. }
  673. });
  674. }
  675. $rootScope.$on('$locationChangeSuccess', function (event, newUrl) {
  676. if (autoRefreshAfterPageLoad) {
  677. $window.location.reload();
  678. }
  679. });
  680. initTheme();
  681. initCheck();
  682. initNavbar();
  683. initContentWrapper();
  684. initFileDragSupport();
  685. }]);
  686. }());