Compare commits

...

819 Commits

Author SHA1 Message Date
Dr_rOot b0242d3d5b chore: bump version v1.6.11 2021-05-15 22:30:00 +08:00
Dr_rOot 58cfd2b873 Merge pull request #944 from agalwood/feature/improve_detail_20210513
feat: improve task detail
2021-05-15 22:27:00 +08:00
Dr_rOot 804f864709 chore: update deps 2021-05-15 22:12:19 +08:00
Dr_rOot 57fb4d95ae feat: get file selection util 2021-05-15 21:59:01 +08:00
Dr_rOot 8030699e15 chore: i18n task select at least one 2021-05-15 21:58:22 +08:00
Dr_rOot 1185a81c0c chore: i18n save & reset 2021-05-15 21:45:41 +08:00
Dr_rOot aa4941f842 feat: save task file selection 2021-05-15 21:44:21 +08:00
Dr_rOot 841bd8b923 fix: task detail activity graphic align center 2021-05-13 21:52:57 +08:00
Dr_rOot 85ae4cdbca Merge pull request #942 from agalwood/hotfix/auto_update_20210511
fix: some bug
2021-05-12 23:34:25 +08:00
Dr_rOot c257816608 fix: element ui message z-index 2021-05-12 22:32:53 +08:00
Dr_rOot 1b44ef725b fix: task detail not auto hide when remove task 2021-05-12 11:47:18 +08:00
Dr_rOot bffe919b93 fix: add one task triggered rename rule 2021-05-12 11:24:51 +08:00
Dr_rOot 87635ade34 fix: auto theme 2021-05-12 11:24:15 +08:00
Dr_rOot c6a9eb226d fix: auto update exception 2021-05-11 15:18:21 +08:00
Dr_rOot da2b6638d9 Merge pull request #939 from agalwood/feature/lab_dark_20210509
feat: preference lab panel dark theme
2021-05-11 15:06:22 +08:00
Dr_rOot 91072509d3 refactor: mo icon 2021-05-09 22:12:47 +08:00
Dr_rOot 0d75370f95 fix: drawer header close icon could not click 2021-05-09 22:12:21 +08:00
Dr_rOot 994d351998 feat: lab page dark theme 2021-05-09 12:07:15 +08:00
Dr_rOot 166aba7747 chore: bump version v1.6.10 2021-05-07 23:22:26 +08:00
Dr_rOot bc3ea97780 Merge pull request #928 from agalwood/hotfix/app_style_20210507
fix: app style
2021-05-07 22:37:43 +08:00
Dr_rOot 2beb6f14a8 chore: update app info icon 2021-05-07 21:49:32 +08:00
Dr_rOot 5d8566a934 feat: mock ua add more ua options 2021-05-07 21:36:52 +08:00
Dr_rOot 84b002d513 feat: add more speed options 2021-05-07 21:25:29 +08:00
Dr_rOot a4fb082088 refactor: style code format 2021-05-07 21:25:04 +08:00
Dr_rOot 3aa18e7f72 fix: revert mac target 2021-05-07 19:19:10 +08:00
Dr_rOot e939f9e5dc Merge pull request #925 from agalwood/hotfix/app_hang_20210507 2021-05-07 16:40:04 +08:00
Dr_rOot 53ec0b1dee chore: update deps 2021-05-07 14:11:34 +08:00
Dr_rOot fcfd32a71e refactor: task detail style 2021-05-07 14:06:35 +08:00
Dr_rOot 2ff56a3770 refactor: task item style 2021-05-07 14:06:28 +08:00
Dr_rOot 48768f0658 fix: copyright year 2021-05-07 14:03:32 +08:00
Dr_rOot 3e84230b33 fix: app reset engine not start 2021-05-07 14:03:13 +08:00
Dr_rOot 5490946267 fix: app hang caused by child_process spawn
https://github.com/electron/electron/issues/24329#issuecomment-760699187
2021-05-07 14:02:48 +08:00
Dr_rOot 9461381042 chore: bump version v1.6.8 2021-05-06 15:30:01 +08:00
Dr_rOot 364d7a8f66 chore: lock electron-builder version to 22.10.5 2021-05-06 15:27:39 +08:00
Dr_rOot 7a5a1554ca chore: bump version & electron-builder -> 22.10.5 2021-05-06 14:58:50 +08:00
Dr_rOot 8410be59b2 chore: bump version 1.6.6 2021-05-06 14:19:22 +08:00
Dr_rOot 795db0b926 chore: github action build force release 2021-05-06 14:18:30 +08:00
Dr_rOot 079cab8544 chore: bump version v1.6.5 2021-05-06 13:57:32 +08:00
Dr_rOot 7109747e00 chore: update github actions 2021-05-06 13:56:57 +08:00
Dr_rOot 9b698f5a0e chore: bump version v1.6.3 2021-05-06 12:05:25 +08:00
Dr_rOot 2b35fb9bc2 chore: bump version v1.6.1 2021-05-06 12:02:41 +08:00
Dr_rOot 2b80127ad0 docs: update readme i18n 2021-05-06 12:01:57 +08:00
Dr_rOot d47fa3d705 chore: bump version to 1.6.0 2021-05-06 11:24:16 +08:00
Dr_rOot 555db61ec0 Merge pull request #922 from agalwood/hotfix/theme_style_20210506
refactor: task detail dark theme style
2021-05-06 11:09:57 +08:00
Dr_rOot 7c2fc774ca chore: update deps 2021-05-06 10:48:31 +08:00
Dr_rOot 8eeab3d3fa feat: task graphic dark theme style 2021-05-06 10:36:33 +08:00
Dr_rOot 7a5b16aecc refactor: task status theme 2021-05-06 10:36:02 +08:00
Dr_rOot c5f72414e2 refactor: preference store actions 2021-05-06 10:35:26 +08:00
Dr_rOot 4016f5c02e Merge pull request #921 from agalwood/feature/task_detail_20210503 2021-05-05 23:20:09 +08:00
Dr_rOot af7eb1f359 Merge branch 'master' into feature/task_detail_20210503 2021-05-05 23:08:19 +08:00
Dr_rOot f30ed3c8f7 fix: update task peers table column width 2021-05-05 22:56:44 +08:00
Dr_rOot e9e86fbc83 refactor: task detail tab content scrollable 2021-05-05 22:36:14 +08:00
Dr_rOot d7b985bc3f docs: update app features 2021-05-05 16:54:40 +08:00
Dr_rOot e307240a60 fix: remove useless code 2021-05-05 16:52:28 +08:00
Dr_rOot 8dd1d84485 chore: i18n task detail 2021-05-05 16:51:12 +08:00
Dr_rOot 3c7b0b26e3 chore: i18n bt settings 2021-05-05 16:26:01 +08:00
Dr_rOot 778e092c17 docs: update contributing locale guide 2021-05-05 15:54:32 +08:00
Dr_rOot 6e462166d1 chore: i18n task files 2021-05-05 11:35:30 +08:00
Dr_rOot 812b419379 chore: update task list i18n 2021-05-05 10:39:21 +08:00
Dr_rOot 04dcddd3e1 docs: update translation contributors 2021-05-05 09:45:23 +08:00
أحمد الطبراني 1cfec289b7 fix: Complete translation into Arabic (#919)
* refactor: Complete translation into Arabic

* refactor: Complete translation into Arabic

* Update preferences.js
2021-05-05 09:41:03 +08:00
Dr_rOot 2dcfb8c25e refactor: change some log 2021-05-04 20:38:47 +08:00
Dr_rOot 482b9312b1 chore: i18n task detail 2021-05-04 15:30:16 +08:00
Dr_rOot dbb1889fc9 feat: task detail 2021-05-04 15:06:44 +08:00
Dr_rOot a6de12c875 feat: task activity 2021-05-04 15:04:02 +08:00
Dr_rOot d14ddef8e8 feat: task peers 2021-05-04 15:03:33 +08:00
Dr_rOot c8698e5b80 refactor: task files component 2021-05-04 15:03:10 +08:00
Dr_rOot e8c99caf87 feat: task trackers 2021-05-04 14:59:31 +08:00
Dr_rOot f70595915d feat: task general info 2021-05-04 14:58:39 +08:00
Dr_rOot c5962041cb feat: task bitfield graphic 2021-05-04 14:55:39 +08:00
Dr_rOot 28bbf26334 refactor: select torrent file list 2021-05-03 20:00:07 +08:00
Dr_rOot 3d6931f8d8 refactor: main menu quit 2021-05-03 19:43:14 +08:00
Dr_rOot 46d686bee5 fix: remove file to trash for electron v11.x 2021-05-03 19:41:41 +08:00
Dr_rOot 9ffaf1116f Merge pull request #915 from agalwood/feature/bt_config_202104231109 2021-05-03 19:19:57 +08:00
Dr_rOot 2d4a05f3b0 chore: update deps lock 2021-05-03 19:01:54 +08:00
Dr_rOot e04d3a582e fix: store task checkTaskIsBT 2021-05-03 18:51:12 +08:00
Hadi Alqattan 943830f2ed feat: Add Arabic Localization
* Partial Arabic Language support!

* Partial Arabic Language support!

* translate more words...
2021-05-03 18:35:58 +08:00
Dr_rOot 137927d44a chore: revert electron from 12.x to 11.x 2021-05-03 18:33:29 +08:00
Dr_rOot 819f86632e feat: task progress info show seeder number 2021-05-03 18:18:55 +08:00
Dr_rOot 06f881932c refactor: dev env add engine log 2021-05-03 18:17:41 +08:00
Dr_rOot cb845ea65a refactor: update pause task speed use force pause 2021-05-03 18:15:24 +08:00
Dr_rOot 60e4907be6 fix: stop seeding params gid 2021-04-26 15:00:59 +08:00
Dr_rOot bc38978d6a refactor: open url external 2021-04-23 17:37:16 +08:00
Dr_rOot 90c3bbff13 fix: deps electron remote 2021-04-23 17:36:45 +08:00
Dr_rOot 3116c53734 refactor: electron remote 2021-04-23 15:12:40 +08:00
Dr_rOot 78fb6ba455 refactor: css-minimizer-webpack-plugin
replace css-minimizer-webpack-plugin with css-minimizer-webpack-plugin
2021-04-23 14:51:41 +08:00
Dr_rOot 86304c126d chore: update deps 2021-04-23 11:48:56 +08:00
Dr_rOot 3424424e67 feat: preference bt setting bt-save-metadata 2021-04-23 11:39:34 +08:00
Dr_rOot 7206f2fc3c Merge pull request #892 from agalwood/feature/bt_202103131952
feat: new app icon & bt setting
2021-04-01 23:39:57 +08:00
Dr_rOot bd25e566c8 chore: i18n zh-TW bt keep seeding 2021-03-24 23:26:02 +08:00
Dr_rOot f54bc32e90 feat: bt keep seeding 2021-03-24 23:23:04 +08:00
Dr_rOot f6dde55234 feat: new app icon 2021-03-13 21:14:43 +08:00
Dr_rOot 1303713f5e feat: reset session 2021-03-13 20:08:14 +08:00
Dr_rOot 57a5c0c932 Merge pull request #877 from agalwood/feature/engine_refactor_202102182037
refactor: replace forever with child process
2021-03-13 19:50:43 +08:00
Dr_rOot 22a41c332f Merge branch 'master' into feature/engine_refactor_202102182037
# Conflicts:
#	yarn.lock
2021-03-13 18:37:25 +08:00
Dr_rOot 76e7223e85 Merge pull request #875 from agalwood/dependabot/npm_and_yarn/elliptic-6.5.4
chore(deps): bump elliptic from 6.5.3 to 6.5.4
2021-03-13 18:35:15 +08:00
Dr_rOot 014619ed46 chore: update deps 2021-03-13 18:29:02 +08:00
Dr_rOot aec3a25e3a chore: engine error code text remove # 2021-03-13 11:23:57 +08:00
dependabot[bot] 02f6ffa3cb chore(deps): bump elliptic from 6.5.3 to 6.5.4
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.3 to 6.5.4.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.3...v6.5.4)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-11 07:16:59 +00:00
Dr_rOot 5d32fc633c feat: add more speed options 2021-03-01 11:12:49 +08:00
Dr_rOot cde2832ae3 chore: aria2 conf http accept gzip 2021-03-01 11:10:02 +08:00
Dr_rOot 8656fa0862 refactor: replace forever with child process 2021-03-01 11:09:14 +08:00
Dr_rOot 0cd1ed1e34 Merge pull request #865 from agalwood/feature/tracker_cdn_202102181833
feat: add tracker cdn source
2021-02-18 20:31:17 +08:00
Dr_rOot d58e485846 refactor: auto sync tracker 2021-02-18 19:03:19 +08:00
Dr_rOot a6aca44672 refactor: preference tracker cdn source select 2021-02-18 18:41:57 +08:00
Dr_rOot cc28e4b19b chore: replace default tracker source config 2021-02-18 18:41:14 +08:00
Dr_rOot 599dec1d6e feat: add tracker cdn urls 2021-02-18 18:35:10 +08:00
Dr_rOot d020359058 Merge pull request #851 from upuppz/master
fix: Function overload error, unable to trigger events bound in EngineClient.vue
2021-01-14 20:23:02 +08:00
upuppz 04d68e293b fix: Function overload error, unable to trigger events bound in EngineClient.vue(函数重载错误, 无法触发在 EngineClient.vue 中绑定的事件) 2021-01-12 18:25:48 +08:00
upuppz 6b93a80888 Merge pull request #4 from agalwood/master
Sync
2021-01-12 18:20:49 +08:00
Dr_rOot c3400d936e Merge pull request #844 from alyn3d/master
feat: Added Romanian translation
2021-01-05 11:12:11 +08:00
alyn3d 871be123d4 feat: Added Romanian translation 2021-01-03 00:29:01 +02:00
Dr_rOot bed2148ba0 Merge pull request #843 from agalwood/hotfix/tray_retina_202012292116
refactor: dynamic tray scale
2020-12-29 21:24:16 +08:00
Dr_rOot 8b97c90e88 refactor: dynamic tray scale 2020-12-29 21:16:36 +08:00
Dr_rOot 832befbafd Merge pull request #842 from agalwood/hotfix/style_202012291454
fix: some style improve
2020-12-29 21:05:31 +08:00
Dr_rOot ddbf27e2f9 refactor: form actions position sticky 2020-12-29 14:55:57 +08:00
Dr_rOot 64b30b6c26 fix: task progress info text font style normal 2020-12-29 14:55:38 +08:00
Dr_rOot 32c8767e65 Merge pull request #840 from agalwood/hotfix/multispinner_202012282315
chore: replace multispinner deps
2020-12-28 23:27:48 +08:00
Dr_rOot 69391c6de0 chore: update deps 2020-12-28 23:21:47 +08:00
Dr_rOot fbec4e7c4d Merge pull request #839 from shatyuka/big_sur_tray
fix: big sur tray color
2020-12-28 23:14:13 +08:00
Shatyuka 7640ba583d fix: big sur tray color 2020-12-28 19:45:53 +08:00
Dr_rOot 924b397727 Merge pull request #838 from agalwood/hotfix/tray_workder_202012271447
fix: tray worker cannot find module 'lodash'
2020-12-27 21:45:06 +08:00
Dr_rOot 565afdde74 chore: update deps & change npm to yarn 2020-12-27 20:07:53 +08:00
Dr_rOot 3dfd4ec4da fix: tray worker cannot find module 'lodash' 2020-12-27 14:47:55 +08:00
Dr_rOot 0a21f590ff Merge pull request #836 from shatyuka/apple_silicon
feat: Support Apple Silicon
2020-12-27 14:45:37 +08:00
カワリミ人形 79bf90bb3c docs: Fix installation instructions in README.md (#834) 2020-12-26 21:09:55 +08:00
Shatyuka f4602b4b68 fix: import JSONRPCError 2020-12-26 13:00:29 +08:00
Shatyuka 93a6f1cfbd fix: Shadow not complete 2020-12-26 12:00:08 +08:00
Shatyuka f0d14afb7e chore: update dependency sass-loader 2020-12-26 11:10:02 +08:00
Shatyuka d9a69ae009 fix: use iframe instead of webview 2020-12-26 09:29:26 +08:00
Shatyuka 0f5398b106 fix: engine failed to quit 2020-12-26 09:03:38 +08:00
Shatyuka c6eb96547a fix: tray menu crash 2020-12-26 07:39:00 +08:00
Shatyuka 31ab487d82 feat: Add native arm support for macos aria2
universal binary
2020-12-26 06:03:36 +08:00
Shatyuka 0b2e271663 feat: Update electron to 11 to support Apple Silicon
Update almost all of the dependencies.
This commit only promises the app would be successfully built and run.
2020-12-26 00:09:44 +08:00
jimman2003 a4a4b2321f fix: updated axios and forever-monitor to get rid of error in dev enviroment (#818) 2020-12-09 20:51:18 +08:00
XIU2 ef372da87b fix: replace TrackersListCollection other.txt with http.txt (#809) 2020-11-25 13:59:00 +08:00
Dr_rOot 10cab1a9a0 docs: readme i18n add Italiano 2020-10-09 21:08:55 +08:00
blackcat-917 a4a651b397 feat: Added Italian language (#794)
* Feat: added italian

* Small fix

* Update index.js to match to the original indent style
2020-10-09 20:56:06 +08:00
Dr_rOot b2770795ad docs: i18n add el (Greek) 2020-08-30 13:22:17 +08:00
Akis S f4c8ff66d5 feat: Added Greek language (#774)
* feat: Added Greek language

* Update index.js
2020-08-30 13:17:49 +08:00
Dr_rOot 1b450c8022 docs: i18n add missing locales es & hu 2020-08-04 21:52:14 +08:00
zalnars e5b8846286 feat: Added Hungarian language (#754)
* Added Hungarian language

* Update all.js

* Update app.js

* Update all.js
2020-07-26 21:06:19 +08:00
Samuel Martineau 8de8591725 fix: correction of the french locale (#742)
* Correction of the French locale

- `transfer-speed-upload`and `transfer-speed-download` were the same
- `transfer-speed-unlimited` was still in English

* fix: correction of the french locale

* fix: correction of the french locale
2020-07-15 20:55:17 +08:00
Dr_rOot 20c30279b0 docs: update readme cn 2020-07-04 21:43:00 +08:00
Stanisław Nieradko 9000be502b feat: Added Polish (#731)
* Added Polish

* Sorted imports in src/shared/locales/app.js
2020-07-04 21:36:34 +08:00
Dr_rOot cfe66cf337 Merge pull request #720 from agalwood/feature/tray_speedometer_202006211216
feat: menu bar tray speedometer #643
2020-06-21 21:30:51 +08:00
Dr_rOot 3557d17bb6 chore: update deps, upgrade electron to 9.x
> That was a bug in Chromium, which got fixed by this [commit](https://chromium.googlesource.com/chromium/src/+/09514b7fbd4fb14ce12a43bc7f4807179612fa94) (available in Chrome v83).

https://stackoverflow.com/questions/61268950/offscreen-converttoblob-very-slow
2020-06-21 21:10:22 +08:00
Dr_rOot 2af891aab8 chore: i18n tray speedometer 2020-06-21 16:23:07 +08:00
Dr_rOot 0d276de39b feat: preference tray speedometer setting 2020-06-21 16:12:35 +08:00
Dr_rOot 8a6beda335 feat: tray speedometer 2020-06-21 16:12:04 +08:00
Dr_rOot 68f1cdc4de chore: update copyright year 2020-06-21 15:30:28 +08:00
Dr_rOot 5290fcfa14 feat: dockmanager add handleSpeedChange 2020-06-21 15:21:06 +08:00
Dr_rOot d865b630a3 refactor: rename enable args 2020-06-21 15:19:50 +08:00
Dr_rOot 9d95d294cd refactor: rename store actions mutations 2020-06-21 13:47:02 +08:00
Dr_rOot ea46d9b3c6 refactor: load config fn use ipc invoke 2020-06-21 12:33:28 +08:00
Dr_rOot ef2c992af9 refactor: remove deprecated fns 2020-06-21 12:30:43 +08:00
Dr_rOot 64ee097c85 Merge pull request #718 from agalwood/feature/stop_seeding_202006201236
fix: stop bt task seeding notification #604
2020-06-20 18:29:48 +08:00
Dr_rOot 31517f93cb chore: i18n stopping seeding tip 2020-06-20 15:51:24 +08:00
Dr_rOot 6d54e557b9 fix: oddly stop seeding notify #604 2020-06-20 15:50:18 +08:00
Dr_rOot 3e61adcea3 Merge pull request #716 from agalwood/feature/url_protocol_202005290826
refactor: redesign motrix scheme
2020-06-20 12:34:52 +08:00
Dr_rOot 84d9ced137 Merge pull request #714 from agalwood/hotfix/hide_run_mode_202006192140
fix: preference show run mode only in macOS
2020-06-19 23:01:36 +08:00
Dr_rOot bc45ed9d5b refactor: add jsconfig 2020-06-19 21:44:53 +08:00
Dr_rOot 3d98104dbf fix: preference show run mode only in macOS 2020-06-19 21:42:00 +08:00
Dr_rOot fb6986ff6e docs: update readme app icon 2020-06-19 20:55:07 +08:00
Dr_rOot b8507570c6 refactor: rename initialForm to initForm 2020-06-12 17:22:38 +08:00
Dr_rOot cf3ef7606c fix: new task uri 2020-06-06 23:31:24 +08:00
Dr_rOot 12a9fa92c1 chore: bump version 2020-06-05 23:54:14 +08:00
Dr_rOot 0fd6617eba docs: update readme i18n 2020-06-05 23:52:34 +08:00
Dr_rOot 7ebbf929d5 fix: i18n no-confirm-before-delete-task missed 2020-06-05 23:49:27 +08:00
Dr_rOot 14223c2204 chore: bump version 2020-06-05 23:26:11 +08:00
Dr_rOot 2cfb6b1914 Merge pull request #689 from agalwood/hotfix/handle_url_202006051331
fix: open app with url handle fail
2020-06-05 14:04:27 +08:00
Dr_rOot c38cf80589 chore: update deps 2020-06-05 13:40:30 +08:00
Dr_rOot 3ee98eae1d fix: open app with resource url 2020-06-05 13:33:22 +08:00
Dr_rOot d2cff6356a Merge pull request #686 from NickoAilus/master
fix: edited Russian locale
2020-06-01 22:12:46 +08:00
NickoAilus 3ee432d683 Fixed Russian locale 2020-06-01 16:10:36 +03:00
Dmitry Kalinin 7f1822bb7e feat: Added bulgarian (bg) translations (#685)
* Added bulgarian (bg) translations

* Improve structure

* Fixed bugs

* Deleted comma
2020-06-01 17:33:46 +08:00
Dr_rOot 0223e691ff docs: readme i18n add vi 2020-05-31 22:57:56 +08:00
Duy–Thanh Doan 117dba9f37 feat: Add vietnamese translation (#680)
* Add vietnamese translation

* Update app.js and index.js

* Translated about.js

* Translated app.js

* first draft

* final draft

* final update - ready to review

* Update format
2020-05-31 22:52:26 +08:00
Dr_rOot e5241d09d7 refactor: protocol manager init 2020-05-29 17:28:03 +08:00
Dr_rOot c9ea1dece2 refactor: motrix url protocol 2020-05-29 17:02:43 +08:00
Dr_rOot 60d4108ddc refactor: promise all to allSettled 2020-05-29 17:00:47 +08:00
Dr_rOot ffc8de4766 refactor: add task utils 2020-05-29 16:58:35 +08:00
Dr_rOot 66f114bf72 Merge pull request #674 from agalwood/hotfix/upnp_cb_202005271904
fix: nat-api autoUpdate cb is not a function
2020-05-28 15:28:28 +08:00
Dr_rOot 44f00483f9 chore: update deps 2020-05-28 14:42:43 +08:00
Dr_rOot 1866e3fd4f fix: nat-api autoUpdate cb is not a function
replace nat-api to @motrix/nat-api

@motrix/nat-api forked from https://github.com/alxhotel/nat-api
2020-05-28 14:42:05 +08:00
Dr_rOot cfac883cbf chore: remove deprecated vue-html-loader 2020-05-28 12:11:30 +08:00
Dr_rOot 1431bab366 Merge pull request #670 from agalwood/hotfix/full_screen_preference_202005271103
fix: full screen save preference issue #663
2020-05-27 11:20:23 +08:00
Dr_rOot bb373947ff fix: full screen save preference issue #663 2020-05-27 11:06:51 +08:00
Dr_rOot 8f0dc65341 refactor: rename auto hide window 2020-05-27 11:06:31 +08:00
Dr_rOot 402185e1a2 chore: bump version 2020-05-25 22:35:09 +08:00
Dr_rOot d59b5c9841 Merge pull request #667 from agalwood/hotfix/refactor_202005231656
fix: upnp client & full screen issues
2020-05-25 22:15:36 +08:00
Dr_rOot eb442e4a7a fix: windows auto launch config lose 2020-05-25 21:55:23 +08:00
Dr_rOot e82e567069 refactor: time constants 2020-05-24 20:15:20 +08:00
Dr_rOot dc2876098d fix: upnp client is destroyed #662 2020-05-24 20:13:43 +08:00
Dr_rOot 6287942fbc fix: full screen mode no traffic light #663 2020-05-24 17:04:08 +08:00
Dr_rOot 389dc080b6 refactor: improve macOS fullscreen mode usability 2020-05-24 15:30:50 +08:00
Dr_rOot 45a23d73e6 fix: code error 2020-05-23 17:16:16 +08:00
Dr_rOot 8303dd305b refactor: fn rename & format 2020-05-23 17:03:45 +08:00
Dr_rOot a98292ce1e refactor: remove title bar buttons spacer 2020-05-23 16:57:01 +08:00
Dr_rOot 8df97b8433 fix: switching system theme will not auto switch app theme 2020-05-22 11:21:45 +08:00
Dr_rOot f29e95c9bc chore: add electron apps banner 2020-05-21 16:32:10 +08:00
Dr_rOot 52e045c886 docs: update readme for github markdown 2020-05-21 08:56:28 +08:00
Dr_rOot 4632c3619a docs: update readme 2020-05-21 08:54:01 +08:00
Dr_rOot 54c48be29b chore: bump version 2020-05-21 07:51:47 +08:00
Dr_rOot 301f1403df Merge pull request #658 from aarestu/translation/indonesia
feat: add Indonesian translations
2020-05-21 07:17:12 +08:00
Dr_rOot 88de047778 Merge pull request #659 from agalwood/hotfix/webpack_copy_202005210655
fix: webpack copy plugin path
2020-05-21 07:07:29 +08:00
Dr_rOot c119de78ce fix: webpack copy plugin path 2020-05-21 06:56:04 +08:00
Restu Suhendar 9d381e16da add translation Indonesia 2020-05-21 04:24:07 +07:00
Dr_rOot e4c6d6a9c0 Merge pull request #655 from agalwood/hotfix/linux_tray_202005202115
fix: linux tray context menu
2020-05-20 21:33:13 +08:00
Dr_rOot 5bb727cb6f chore: update deps 2020-05-20 21:16:35 +08:00
Dr_rOot 00f3209c68 refactor: improve logs 2020-05-20 21:16:11 +08:00
Dr_rOot 3f8b0e6f5f fix: tray popUpContextMenu linux not support 2020-05-20 21:16:01 +08:00
Dr_rOot 0543bc4e2c chore: bump version 2020-05-20 16:32:55 +08:00
Dr_rOot 9ded42f127 chore: update docs 2020-05-20 13:53:20 +08:00
Dr_rOot 834a1ad839 docs: update readme linux section 2020-05-20 11:30:50 +08:00
Dr_rOot 8f830f6a0d fix: too fast to toggle tracker syncing spinner 2020-05-20 11:10:59 +08:00
Dr_rOot ee111c92ee fix: too fast to shut down the engine 2020-05-20 11:09:50 +08:00
Dr_rOot 74c3a3c696 Merge pull request #650 from agalwood/hotfix/linux_tray_20200519
fix: linux tray not support right-click event
2020-05-19 22:06:45 +08:00
Dr_rOot 4d964ae16e fix: tray destroy remove listener 2020-05-19 21:50:36 +08:00
Dr_rOot be2c2e8383 docs: update readme snapcraft markdown 2020-05-19 12:23:31 +08:00
Dr_rOot 4e6164816f fix: linux tray not support right click 2020-05-19 12:23:00 +08:00
Dr_rOot fa7daf377f docs: update app screenshots 2020-05-18 14:24:06 +08:00
Dr_rOot afbe364525 docs: fix release badge 2020-05-18 13:43:36 +08:00
Dr_rOot ece5cea512 docs: update readme 2020-05-18 13:37:36 +08:00
Dr_rOot dc8fa5c647 chore: bump version v1.5.10 2020-05-15 21:54:16 +08:00
Dr_rOot 4fd96e7cae chore: bump version v1.5.9 2020-05-15 21:45:22 +08:00
Dr_rOot 1f22b5efba Merge pull request #640 from agalwood/hotfix/task_manager_202005151229
fix: save session delay too long
fix: hide delete selected tasks on stopped task list
2020-05-15 16:44:31 +08:00
Dr_rOot 801db0ed38 chore: upgrade electron 2020-05-15 12:34:39 +08:00
Dr_rOot f72577de65 fix: hide delete selected tasks on stopped task list 2020-05-15 12:33:58 +08:00
Dr_rOot dd21c76dea fix: save session delay too long 2020-05-15 12:29:51 +08:00
Dr_rOot 5a5a932735 Merge pull request #639 from agalwood/feature/no_confirm_202005062312
feat: no confirm before delete task
feat: add task select video include sub files
feat: preference support add custom tracker source #627
feat: Ctrl or ⌘ + Enter quick submit task #638
feat: improve task total length is zero ui #614
fix: split & max-connection-per-server failed #270
fix: npm build:clean script
2020-05-15 00:03:54 +08:00
Dr_rOot d63c1d431d feat: improve task total length is zero ui #614 2020-05-14 23:43:42 +08:00
Dr_rOot 1a12256c4c feat: Ctrl or ⌘ + Enter quick submit task 2020-05-14 23:40:37 +08:00
Dr_rOot 9394a0a79b chore: update deps & bump version 2020-05-14 22:27:44 +08:00
Dr_rOot 5e66205298 chore: disable electron security warnings 2020-05-14 22:26:34 +08:00
Dr_rOot eb796c3c5f feat: add task select video include sub files 2020-05-14 22:26:11 +08:00
Dr_rOot 9d17b3e9b2 fix: split & max-connection-per-server failed #270 2020-05-14 22:25:35 +08:00
Dr_rOot 7ee8d4fa0f refactor: engine instance listeners 2020-05-14 22:21:57 +08:00
Dr_rOot dba4bfb0e7 fix: perference sync tracker empty 2020-05-14 22:20:23 +08:00
Dr_rOot f9755f69cd chore: improve aria2 bt config 2020-05-14 22:20:02 +08:00
Dr_rOot 7a68e1bb82 fix: npm build:clean script 2020-05-14 22:14:18 +08:00
Dr_rOot 3b12f3960f refactor: code format 2020-05-14 22:13:56 +08:00
Dr_rOot dbe26dfa98 feat: preference support add custom tracker source 2020-05-14 22:12:34 +08:00
Dr_rOot 3be8952cff refactor: task actions commands 2020-05-14 22:08:59 +08:00
Dr_rOot dc5a368e00 Merge pull request #630 from agalwood/hotfix/aria2c_darwin_202005081709
fix: rebuild darwin aria2c v1.35

closed #628
2020-05-08 17:30:53 +08:00
Dr_rOot 11aca7ea0b chore: remove bt-force-encryption 2020-05-08 17:16:48 +08:00
Dr_rOot c35af2b109 fix: rebuild aria2c #628
static build script:
https://github.com/aria2/aria2/blob/master/
makerelease-osx.mk
2020-05-08 17:12:04 +08:00
Dr_rOot b33b505ccb refactor: upnp close client 2020-05-06 23:21:49 +08:00
Dr_rOot dd22cc0306 fix: remove enable egg features config 2020-05-06 23:19:58 +08:00
Dr_rOot 206eda08aa refactor: renderer native utils 2020-05-06 23:19:08 +08:00
Dr_rOot f6e29700d0 feat: no confirm before delete config 2020-05-06 23:16:50 +08:00
Dr_rOot c17ceb365d chore: upgrade electron-builder 2020-05-03 23:00:41 +08:00
Dr_rOot a1851c6b31 chore: bump version v1.5.6 2020-05-03 22:10:32 +08:00
Dr_rOot 071b0a21c2 chore: bump version v1.5.5 2020-05-03 21:58:39 +08:00
Dr_rOot e25dfb143c Merge pull request #621 from agalwood/hotfix/prepare_release_202004280758
refactor: redesigned the lab page
2020-05-03 21:32:12 +08:00
Dr_rOot 652f04bada chore: bump version 2020-05-03 20:26:06 +08:00
Dr_rOot 5962334f3d feat: new lab page 2020-05-03 20:25:32 +08:00
Dr_rOot f984b175dc refactor: code format 2020-05-03 20:25:05 +08:00
Dr_rOot ad1979417a refactor: engine config 2020-04-30 22:22:48 +08:00
Dr_rOot 16822b9b55 Merge pull request #618 from agalwood/feature/upgrade_aria2_202004302143
feat: upgrade aria2 to v1.35.0
2020-04-30 22:15:34 +08:00
Dr_rOot 36551da19e refactor: arai2 config 2020-04-30 21:46:01 +08:00
Dr_rOot f3426fdc90 chore: upgrade aria2 version to 1.35.0
Compile it with reference to the script of q3aql/aria2-static-builds. The difference from the official version of Aria2 is that the max-connection-per-server is modified to 64.

https://github.com/q3aql/aria2-static-builds
2020-04-30 21:45:46 +08:00
Dr_rOot 94ead296bf docs: update readme 2020-04-30 13:26:40 +08:00
Dr_rOot 22a6f73e51 Merge pull request #616 from agalwood/feature/github_action_202004292314
feat: github action
2020-04-30 11:47:28 +08:00
Dr_rOot 94b4c08da9 fix: travis ci rpm 2020-04-30 11:03:52 +08:00
Dr_rOot 041b7701c2 fix: remove pacman 2020-04-30 00:23:27 +08:00
Dr_rOot c20d9b65ee fix: github action mac build notarize 2020-04-30 00:10:57 +08:00
Dr_rOot 47c5daea81 feat: test github action 2020-04-29 23:15:45 +08:00
Dr_rOot 9676e2a060 fix: remove ci node-sass config 2020-04-28 22:50:52 +08:00
Dr_rOot bb75fa6dcc refactor: change drag select color 2020-04-28 13:28:36 +08:00
Dr_rOot b547ef8f2e refactor: improve shutdown upnp speed 2020-04-28 13:22:20 +08:00
Dr_rOot cc44e21d0e feat: implemented menu pause & resume task 2020-04-28 13:22:20 +08:00
Dr_rOot 20ac050514 Merge pull request #615 from agalwood/hotfix/update_deps_202004271523
chore: update dependencies
2020-04-28 08:27:31 +08:00
Dr_rOot 7eeafb6c93 chore: update deps 2020-04-28 08:15:52 +08:00
Dr_rOot 6fd63c872f fix: windows aria2 cmd
revert forever-monitor version to 1.7.2

https://github.com/foreversd/forever-monitor/commit/93cfbef1c5248eeccf00f4d760c04625476aeb51#commitcomment-37379168
2020-04-28 07:56:54 +08:00
Dr_rOot b8b4f04423 chore: bump version 2020-04-27 23:36:30 +08:00
Dr_rOot e3e2abac6f chore: js code format 2020-04-27 23:33:48 +08:00
Dr_rOot b34f3ceb89 chore: vue code format 2020-04-27 23:30:17 +08:00
Dr_rOot feb07a43e1 chore: upgrade babel & eslint 2020-04-27 23:28:38 +08:00
Dr_rOot 4652672ef4 refactor: replace node-sass to dart-sass 2020-04-27 23:23:45 +08:00
Dr_rOot 8b375c019d refactor: code format 2020-04-27 17:59:45 +08:00
Dr_rOot e232e4af70 fix: upnp config watch 2020-04-27 10:02:12 +08:00
Dr_rOot f57d71cebe Merge pull request #611 from agalwood/feature/upnp_202004222153
feat: UPnP support

Closed #411
2020-04-26 23:08:27 +08:00
Dr_rOot 90daf4cb19 chore: bump version 2020-04-22 22:01:37 +08:00
Dr_rOot d1f759ec44 fix: update task progress info with 2020-04-22 22:00:22 +08:00
Dr_rOot 45ad6dfbda chore: update chrome ua 2020-04-22 21:59:35 +08:00
Dr_rOot 65d45f69fe fix: engine shutdown 2020-04-22 21:59:25 +08:00
Dr_rOot 7e626704ac feat: router upnp mapping 2020-04-22 21:58:53 +08:00
Dr_rOot e0f9dce952 Merge pull request #605 from agalwood/hotfix/app_improve_202004062214
refactor: app improve
Closed #588 #547 #491 #484 #481 #439 #425 #410 #376 #174 #106 #85 #27 #560 #413 #598 #551 #603
2020-04-21 18:01:26 +08:00
Dr_rOot edf627923e fix: after sign hook 2020-04-21 17:47:24 +08:00
Dr_rOot 40f7abcc22 fix: drag select components path at linux 2020-04-21 17:36:13 +08:00
Dr_rOot d837e97d02 fix: dev build html webpack plugin 2020-04-21 17:32:48 +08:00
Dr_rOot 13034b4e90 chore: update deps & bump version to 1.5.x 2020-04-21 17:32:30 +08:00
Dr_rOot b3826032ea refactor: max connection per server 2020-04-20 21:40:31 +08:00
Dr_rOot d5e9ada2c9 chore: i18n batch delete task 2020-04-19 15:32:51 +08:00
Dr_rOot 724a2a7f76 fix: aria2 bt conf 2020-04-18 18:02:07 +08:00
Dr_rOot 64326a11af feat: select all task hotkey 2020-04-18 18:01:26 +08:00
Dr_rOot b00536a0c7 feat: task list drag select & batch delete task 2020-04-18 17:31:11 +08:00
Dr_rOot 8885e63474 feat: drag select component
forked from andi23rosca/drag-select-vue
2020-04-18 16:47:14 +08:00
Dr_rOot 28936fd13e feat: batch remove task api 2020-04-18 16:21:00 +08:00
Dr_rOot 08a419f209 refactor: task progress info 2020-04-18 13:18:30 +08:00
Dr_rOot 8a3391c9f4 fix: restart task option split 2020-04-18 11:26:58 +08:00
Dr_rOot 3777a1f753 refactor: remove task 2020-04-18 11:26:11 +08:00
Dr_rOot b81298d6eb refactor: batch change task option api 2020-04-18 11:20:18 +08:00
Dr_rOot f67b9b8dd6 refactor: task status 2020-04-18 10:38:05 +08:00
Dr_rOot a303afb9a5 refactor: improve max connection per server 2020-04-17 22:44:35 +08:00
Dr_rOot eee07b1b7d chore: update readme features 2020-04-15 23:57:00 +08:00
Dr_rOot a27c49a376 chore: update readme 2020-04-15 21:23:21 +08:00
Dr_rOot fd81dc5194 fix: get random int util 2020-04-13 21:24:21 +08:00
Dr_rOot 394dfdfffc chore: i18n bt listen ports 2020-04-13 21:22:25 +08:00
Dr_rOot 99e9aa8046 feat: advanced preference bt listen ports setting 2020-04-12 22:23:43 +08:00
Dr_rOot ec295b3d72 refactor: is renderer linux mas 2020-04-12 19:57:10 +08:00
Dr_rOot 8208440987 feat: bt listen ports config 2020-04-12 19:52:37 +08:00
Dr_rOot 47426f2d66 refactor: import code format 2020-04-12 15:41:16 +08:00
Dr_rOot ac75a05511 refactor: tray manager 2020-04-12 15:31:23 +08:00
Dr_rOot c3ff1f3b23 refactor: log format 2020-04-11 14:22:15 +08:00
Dr_rOot 0f3157980c refactor: remove outdated trackers 2020-04-10 21:12:59 +08:00
Dr_rOot 36929f9dc5 feat: fetch task item peers api 2020-04-07 11:19:19 +08:00
Dr_rOot 11c507008b refactor: app quit 2020-04-06 22:32:44 +08:00
Dr_rOot 3d66549849 fix: preference diff changed 2020-04-06 22:15:44 +08:00
Dr_rOot 47ca535268 fix: main engine client add catch 2020-04-06 22:15:12 +08:00
Dr_rOot 7d102f9fcb fix: constants duplicate declaration 2020-04-06 22:11:22 +08:00
Dr_rOot edf350adf3 Merge pull request #596 from agalwood/hotfix/task_dir_202004061122
fix: several file path related issues

closed #575
2020-04-06 16:56:03 +08:00
Dr_rOot 651f28e7e8 refactor: add task type constant 2020-04-06 16:36:36 +08:00
Dr_rOot 4d7acb7c0a refactor: app theme constant 2020-04-06 16:31:42 +08:00
Dr_rOot b75e969a01 refactor: move task files to trash 2020-04-06 14:46:55 +08:00
Dr_rOot 0b6f5e7d43 refactor: show item in folder 2020-04-06 14:46:45 +08:00
Dr_rOot a82000a13b refactor: temp disabled prettifyDir 2020-04-06 11:27:44 +08:00
Dr_rOot edee889a1a docs: update travis-ci build status badge url 2020-04-05 23:19:29 +08:00
Dr_rOot afd2fdeabf Merge pull request #594 from agalwood/feature/proxy_setting_20200405227
feat: improve proxy setting
2020-04-05 23:18:43 +08:00
Dr_rOot 34011d7bc8 refactor: move rename utils location 2020-04-05 22:50:30 +08:00
Dr_rOot 6cf6b69f8e chore: i18n add task proxy 2020-04-05 22:49:58 +08:00
Dr_rOot a386c704e4 feat: add task support use proxy 2020-04-05 22:49:40 +08:00
Dr_rOot 0994244b0e chore: i18n no proxy input tip 2020-04-05 22:48:37 +08:00
Dr_rOot 777977e001 feat: advanced preference no proxy setting 2020-04-05 22:48:07 +08:00
Dr_rOot af5ac44dc8 Merge pull request #592 from agalwood/hotfix/update_ci_conf_202004052048
chore: update ci conf
2020-04-05 21:46:02 +08:00
Dr_rOot 23382a9415 chore: update ci conf 2020-04-05 20:50:55 +08:00
Dr_rOot 7b2da0f35b Merge pull request #590 from agalwood/feature/tracker_source_202002091515
feat: sync tracker add more source and support auto sync tracker data daily
2020-04-05 12:36:19 +08:00
Dr_rOot 4037dad582 docs: update readme add install electron guide 2020-03-22 23:32:45 +08:00
Dr_rOot 353ee23cfc feat: preference show last sync tracker time 2020-02-23 22:19:45 +08:00
Dr_rOot 29b0d90bc7 fix: Application showPage fn may cause memory leak
MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 ready-to-show listeners added to [BrowserWindow]. Use emitter.setMaxListeners() to increase limit
2020-02-23 12:08:41 +08:00
Jiaqi Gu 073e514f95 feat: Automatically hide window when losing focus (#557)
Automatically hide window when losing focus
2020-02-23 11:59:19 +08:00
Dr_rOot a35fba4820 fix: i18n uk transfer settings 2020-02-22 15:47:28 +08:00
Dr_rOot 828d854eb5 chore: i18n sync tracker 2020-02-22 15:46:04 +08:00
Dr_rOot 5dbe157170 feat: auto sync tracker when app launch 2020-02-21 22:26:22 +08:00
Dr_rOot cdc196c2b0 refactor: save preference config 2020-02-21 22:21:05 +08:00
Dr_rOot 3d26445953 refactor: app updater auto check 2020-02-21 22:15:41 +08:00
Dr_rOot f887878b9e feat: main init engine client 2020-02-21 22:11:07 +08:00
Dr_rOot 908f60df1a feat: advanced preference auto sync tracker 2020-02-21 22:04:45 +08:00
Dr_rOot 56c9b58d87 refactor: advanced preference sync tracker 2020-02-20 19:29:54 +08:00
Dr_rOot d56983d45d refactor: fetch bt tracker data 2020-02-20 19:23:48 +08:00
Dr_rOot 8775e12587 refactor: launcher callback 2020-02-19 20:45:48 +08:00
Dr_rOot df2e01813e feat: add trackers blacklist constant 2020-02-18 17:08:01 +08:00
Dr_rOot d77a6faf36 fix: aria2 bt conf 2020-02-16 13:42:46 +08:00
Dr_rOot 5e735b513d feat: task show connections 2020-02-12 16:12:57 +08:00
Dr_rOot 64f0a3db80 fix: sync old data when tracker source changed 2020-02-10 11:05:38 +08:00
Dr_rOot e470ed00d6 refactor: engine rpc config 2020-02-09 15:51:01 +08:00
Dr_rOot 36a27bae46 feat: preference select sync tracker source 2020-02-09 15:44:55 +08:00
Dr_rOot 5d900806e8 fix: system engine config keys 2020-02-09 15:34:45 +08:00
Dr_rOot ace14c85dc refactor: improve ui style 2020-02-09 15:33:13 +08:00
Dr_rOot 3ec4bd26e6 refactor: update manager last check update time 2020-02-09 15:32:04 +08:00
Dr_rOot b9bc5e6c07 feat: auto remove aria2c unrecognized options 2020-02-09 15:23:00 +08:00
Dr_rOot 021fbc243a refactor: rename & add tracker source 2020-02-09 15:21:55 +08:00
Dr_rOot 8b66f2ea6e refactor: make tracker unique 2020-02-09 15:18:11 +08:00
Dr_rOot 7703c28c6e Merge pull request #544 from agalwood/feature/win_title_bar_202002081321
feat: improve win & linux title bar style

Closes #461
2020-02-08 16:07:08 +08:00
Dr_rOot 26db88ec51 refactor: adjust close btn color for win & linux 2020-02-08 13:23:35 +08:00
Dr_rOot 51b7ea4030 refactor: remove title bar button spacing 2020-02-08 13:22:02 +08:00
Dr_rOot 1e2368dd3b docs: update contribution guide 2020-02-08 12:50:04 +08:00
Dr_rOot f28c3ae5c5 fix: adapt the new api of Electron's TouchBar 2020-02-06 22:22:00 +08:00
Dr_rOot ebdd125d91 Merge pull request #529 from agalwood/feature/proxy_tip_202001311802
feat: Perference advanced panel add proxy tip

close #488
2020-01-31 18:50:14 +08:00
Dr_rOot 9bcc386269 feat: perference advanced proxy tip i18n 2020-01-31 18:16:04 +08:00
Dr_rOot 27c48af278 feat: advanced perference add proxy tip 2020-01-31 18:15:37 +08:00
Dr_rOot 4b4df884dc Merge pull request #528 from agalwood/feature/run_mode_202001311505
feature: Preferences add Run Mode setting

close #345 #350
2020-01-31 16:02:10 +08:00
Dr_rOot 64082ddd70 fix: i18n rename appLocalePtBr to appLocalePtBR 2020-01-31 15:45:12 +08:00
Dr_rOot 188a39d0d2 refactor: i18n rename ru-RU to ru 2020-01-31 15:44:30 +08:00
Dr_rOot 44f8f23a7c feat: run mode i18n 2020-01-31 15:37:56 +08:00
Dr_rOot 32340218e2 refactor: change dock state use DockManager 2020-01-31 15:20:01 +08:00
Dr_rOot 85a8430c3f refactor: ipc change update menu state to command 2020-01-31 15:17:45 +08:00
Dr_rOot e47816e273 refactor: save preference use ipc message 2020-01-31 15:15:55 +08:00
Dr_rOot b7356702fc feat: add DockManager 2020-01-31 15:10:51 +08:00
Dr_rOot a61c857e11 feat: add run mode config 2020-01-31 15:09:31 +08:00
Dr_rOot d3ef30d943 refactor: speed options i18n 2020-01-31 15:07:49 +08:00
Dr_rOot b8d5eb5ac1 fix: add task out i18n 2020-01-31 15:06:14 +08:00
Dr_rOot aeaf0fe9ca Merge pull request #527 from agalwood/feature/improve_responsive_202001311239
feature: improve responsive 202001311239
2020-01-31 14:20:24 +08:00
Dr_rOot 8bebb942ca fix: remove TaskSwitch 2020-01-31 14:11:25 +08:00
Dr_rOot f0e795f00c refactor: code format 2020-01-31 12:49:24 +08:00
Dr_rOot 7d4eec6b02 feat: preference responsive subnav switcher 2020-01-31 12:45:30 +08:00
Dr_rOot fe2dc7a541 refactor: task subnav switcher 2020-01-31 12:42:39 +08:00
Dr_rOot 848b9e78e1 Merge pull request #525 from agalwood/hotfix/fix_open_dialog_202001301122
fix: electron v7 dialog showOpenDialog promisify
2020-01-30 15:14:00 +08:00
Dr_rOot 2fa33f75e5 fix: electron v7 dialog showOpenDialog promisify 2020-01-30 11:25:34 +08:00
Dr_rOot 1f6c2a6ff0 Merge pull request #524 from agalwood/hotfix/upgrade_deps_202001232019
fix: upgrade deps 202001232019
2020-01-30 00:05:09 +08:00
Dr_rOot a8e3c7843c fix: ci node sass 2020-01-29 23:52:04 +08:00
Dr_rOot 8b1ba2425c chore: update ci 2020-01-29 23:37:19 +08:00
Dr_rOot 47acf4fad1 fix: remove select torrent checkbox ellipsis 2020-01-28 13:55:53 +08:00
Dr_rOot 9beb48be92 fix: wrong eslint rule place 2020-01-28 13:55:17 +08:00
Dr_rOot bbe52a2a18 chore: update chrome ua 2020-01-28 13:54:27 +08:00
Dr_rOot 0b73028412 refactor: app info engine title style 2020-01-26 23:21:33 +08:00
Dr_rOot 2311a7ed86 fix: catch vue router NavigationDuplicated error 2020-01-25 02:41:46 +08:00
Dr_rOot 95ed300d1b refactor: nativeTheme.shouldUseDarkColors
systemPreferences.isDarkMode()
**Deprecated:** Should use the new `nativeTheme.shouldUseDarkColors` API.
2020-01-25 02:37:28 +08:00
Dr_rOot dcd2d50c83 refactor: dialog.showMessageBox promisify 2020-01-24 22:17:06 +08:00
Dr_rOot 57ed6c7941 chore: upgrade deps 2020-01-23 21:40:12 +08:00
Dr_rOot 870c4089fb refactor: replace babili with terser 2020-01-23 21:39:00 +08:00
Dr_rOot 1082f9330e refactor: upgrade sass loader 2020-01-23 21:37:15 +08:00
Dr_rOot a7f33869a0 chore: daysUntilLock increase to 60 2020-01-05 17:12:01 +08:00
han 89336dda37 feat: make Motrix layout more responsive (#505) 2020-01-05 17:07:09 +08:00
Dr_rOot 4240dee426 Merge pull request #472 from kant/patch-6
fix: Typos fixed and some translation redone
2019-12-12 16:20:33 +08:00
Dr_rOot 83c1c1340e Merge pull request #471 from kant/patch-5
fix: Typos fixed and some translations redone
2019-12-12 16:20:24 +08:00
Dr_rOot 408e33adb1 Merge pull request #470 from kant/patch-4
fix: Typos and bad translations redone
2019-12-12 16:20:15 +08:00
Dr_rOot d2dde274d3 Merge pull request #469 from kant/patch-2
fix: Typo fixed on line 02
2019-12-12 16:20:03 +08:00
Darío Hereñú 7b27f82f1e Typos fixed and some translation redone 2019-11-11 01:49:12 -03:00
Darío Hereñú 2d32a2848c Typos fixed and some translations redone 2019-11-11 01:39:32 -03:00
Darío Hereñú c128689b2e Typos and translation redone 2019-11-11 01:32:57 -03:00
Darío Hereñú 7702aa6ca1 Typos and bad translations redone 2019-11-11 01:29:28 -03:00
Darío Hereñú 2fb32fa347 Typo fixed on line 02 2019-11-11 01:24:48 -03:00
Dr_rOot 2744db2d75 docs: update readme i18n add ca 2019-11-05 23:15:31 +08:00
Dr_rOot adb060b076 Merge pull request #467 from marcizhu/master
feat: add Catalan translation
2019-11-05 23:07:21 +08:00
marcizhu 561d7608d8 feat: add Catalan translation 2019-11-05 11:53:01 +01:00
Dr_rOot 06d9a95827 Merge pull request #424 from agalwood/hotfix/webpack_config_4node12_201909161132
fix: process is not defined at node 12.x #267
2019-09-16 12:08:32 +08:00
Dr_rOot 9c386c4bdc fix: process is not defined at node 12.x #267
https://github.com/SimulatedGREG/electron-vue/issues/871#issuecomment-490370237
2019-09-16 11:34:12 +08:00
Dr_rOot a1eb48926a Merge pull request #420 from agalwood/feature/custom_tracker_source_201909091524
feat: user config custom tracker source
2019-09-09 16:03:58 +08:00
Dr_rOot c1ed827244 feat: add custom tracker source to user config 2019-09-09 15:49:28 +08:00
Dr_rOot 663e1a2db1 refactor: empty string constant 2019-09-09 15:47:56 +08:00
Dr_rOot c0a2b50b9f Merge pull request #419 from agalwood/hotfix/fix_energy_manager_201909091450
fix: stopPowerSaveBlocker when psbId = 0

closed #418
2019-09-09 15:22:04 +08:00
Dr_rOot a843ae4553 fix: stopPowerSaveBlocker when psbId = 0 2019-09-09 14:49:35 +08:00
Rodolfo Robles d195b23512 feat: Spanish Translation (#385) 2019-08-08 11:16:39 +08:00
Zaoqi f6c84b7e57 docs: add extra/README.md 2019-08-06 10:41:46 +08:00
Dr_rOot 98df9c3f2a fix: magnet and thunder protocol handle 2019-07-22 20:04:36 +08:00
Dr_rOot 7e703eb552 chore: update license copyright 2019-07-21 12:38:34 +08:00
Dr_rOot 87bcac6122 fix: update copyright #365
Closed #365
2019-07-21 12:38:27 +08:00
Dr_rOot 6935a12289 chore: readme i18n add ru 2019-07-13 22:49:40 +08:00
Dr_rOot 39688b667e Merge pull request #358 from bladeaweb/feature/ru
feat: Added Russian localisation.
2019-07-13 22:43:53 +08:00
Alexander Sharkov f174887f9f fix: Removed not requirement changes. 2019-07-13 17:08:37 +03:00
Alexander Sharkov caba086651 fix: Fixed some required changes of language short name. 2019-07-13 16:06:41 +03:00
Dr_rOot b627b38985 Merge pull request #357 from bladeaweb/feature/uk
fix: Fixed spelling issue.
2019-07-13 20:31:12 +08:00
Alexander Sharkov 1c35d72aa5 fix: Fixed spelling issue. 2019-07-13 15:06:17 +03:00
Alexander Sharkov 8ecbfdd66d feat: Added Russian localisation. 2019-07-13 15:03:39 +03:00
Dr_rOot 3be568f6ab Merge pull request #354 from agalwood/hotfix/preferences_changed_201907042031
fix: preferences changed data outdated
2019-07-11 11:35:01 +08:00
Dr_rOot fa29c11c73 Merge pull request #353 from agalwood/feature/shift_delete_201907032126
feat: shift delete task with files
2019-07-10 21:42:00 +08:00
Dr_rOot 6b153d68b4 docs: add tips of first launch in linux 2019-07-08 15:55:18 +08:00
Dr_rOot 852266dc16 refactor: preferences function 2019-07-04 21:09:39 +08:00
Dr_rOot 4170cd3419 refactor: lab preferences 2019-07-04 21:04:34 +08:00
Dr_rOot a15870871f fix: advanced preferences changed 2019-07-04 20:57:24 +08:00
Dr_rOot 571499caad fix: basic preferences changed 2019-07-04 20:37:56 +08:00
Dr_rOot 766c2c26b8 feat: shift trash task auto checked remove files 2019-07-03 21:34:27 +08:00
Dr_rOot 1f27f88aa7 feat: shift delete task auto checked remove files 2019-07-03 21:34:11 +08:00
Dr_rOot e06888e998 chore: add pull request template 2019-07-02 20:21:11 +08:00
Dr_rOot 91a2d0a270 Merge pull request #341 from agalwood/feature/download_outs_201907011638
feat: add task out support rule #326

Closed #326
2019-07-01 20:33:06 +08:00
Dr_rOot 8e3fe4c980 refactor: buildRule operator default PLUS 2019-07-01 20:16:26 +08:00
Dr_rOot f3724107f0 refactor: rule operators 2019-07-01 20:14:02 +08:00
Dr_rOot 580c32a2b9 Merge pull request #340 from agalwood/feature/save_preferences_201906271147
fix: check changed preferences is need restart
2019-07-01 18:56:10 +08:00
Dr_rOot 575712ba9f feat: add task support out rule #326
Out rule sample:
abc_(001+).jpg
xyz_(100-2).html
2019-07-01 18:35:10 +08:00
Dr_rOot 84006f348c feat: add buildOuts util 2019-07-01 18:22:04 +08:00
Dr_rOot a9759441d3 chore: update readme 2019-06-30 10:44:11 +08:00
Dr_rOot 728f8e9019 fix: readme i18n typo #338
closed #338
2019-06-30 10:43:27 +08:00
Dr_rOot e814210896 chore: update getLanguage comments 2019-06-29 00:24:54 +08:00
Dr_rOot a0c6877524 fix: remove useless fallback 2019-06-29 00:24:44 +08:00
Dr_rOot 29b0dd627d Merge pull request #334 from bladeaweb/feature/uk
feat: added Ukrainian localisation.
2019-06-29 00:10:16 +08:00
Alexander Sharkov dc48cad7e8 Added: Ukrainian localisation. 2019-06-28 12:47:26 +03:00
Dr_rOot 35df1c799b fix: check changed preferences is need restart 2019-06-27 15:03:08 +08:00
Dr_rOot 912e661c02 chore: update developer tools tips 2019-06-27 11:32:58 +08:00
Dr_rOot 1a2de2ad88 Merge pull request #323 from agalwood/feature/prepare_v4_201906201052
chore: prepare for release v1.4.x
2019-06-24 00:08:19 +08:00
Dr_rOot e44587035d fix: bump version to 1.4.1 2019-06-23 22:58:59 +08:00
Dr_rOot 43f1adcd84 fix: electron 5.0 performance is low revert to 424 2019-06-22 20:46:29 +08:00
Dr_rOot 8a900459b5 refactor: auto copy changed rpc secret 2019-06-22 20:39:38 +08:00
Dr_rOot d2f8a4599d feat: auto copy rpc url when dice changed secret 2019-06-21 15:46:11 +08:00
Dr_rOot 9159fb36ab chore: bump version to v1.4.0 2019-06-21 14:58:07 +08:00
Dr_rOot 5be05395f5 chore: upgrade dependencies 2019-06-21 14:57:45 +08:00
Dr_rOot fba76df945 fix: change app update url 2019-06-21 14:43:32 +08:00
Dr_rOot 5bb4f259cd fix: set bt-detach-seed-only=true 2019-06-21 14:42:57 +08:00
Dr_rOot 4b093a1a4f fix: increase the number of egine process restarts 2019-06-21 14:41:28 +08:00
Dr_rOot 134d81b205 fix: task stop seeding 2019-06-21 14:40:15 +08:00
Dr_rOot d5fc962bca fix: change task option 2019-06-21 14:40:04 +08:00
Dr_rOot 0d1b76d523 fix: checkTaskIsSeeder util 2019-06-20 15:28:28 +08:00
Dr_rOot 6499ce91b8 refactor: update element ui theme chalk 2019-06-20 11:49:30 +08:00
Dr_rOot 2d7907f218 chore: improve npm scripts postinstall 2019-06-20 11:19:54 +08:00
Dr_rOot 97c1cb0418 fix: change rpc doc link 2019-06-20 11:17:16 +08:00
Dr_rOot be585ef102 refactor: move bt-tracker config manager to file 2019-06-20 10:57:48 +08:00
Dr_rOot 03002221e7 Merge branch 'feature/task_list_201905312258'
# Conflicts:
#	src/renderer/components/Native/EngineClient.vue
2019-06-20 10:38:58 +08:00
Dr_rOot 4b8de781a4 refactor: improve download error message #293 2019-06-19 19:56:07 +08:00
Dr_rOot 8224423d8c refactor: update panel content padding 2019-06-18 21:07:14 +08:00
Dr_rOot 1e05e1e4f3 fix: element ui message link color 2019-06-17 20:27:51 +08:00
Dr_rOot bfd1e1b6fa refactor: removeTaskRecord error complete removed 2019-06-17 19:48:57 +08:00
Dr_rOot 79495cbde5 refactor: auto save session when save preferences 2019-06-16 23:44:49 +08:00
Dr_rOot a93d183988 fix: disabled certificate check 2019-06-16 21:30:24 +08:00
Dr_rOot cf082b20d8 fix: there is no localhost rule in /etc/hosts 2019-06-15 23:09:29 +08:00
Dr_rOot 8110409402 feat: empty addTaskOptions when task added 2019-06-15 20:23:11 +08:00
Dr_rOot 37b446b6f0 feat: add parseHeader util for restart task dialog 2019-06-14 23:22:36 +08:00
Dr_rOot 97801fff32 refactor: task item actions restart & stop seeding 2019-06-14 22:38:07 +08:00
Dr_rOot 4ca4f5e606 refactor: add task to support addTaskOptions 2019-06-14 22:20:34 +08:00
Dr_rOot e9caf1b0b4 refactor: transform add options keys to kebab case 2019-06-13 20:47:33 +08:00
Dr_rOot d67dca00b5 feat: add getTaskOption action 2019-06-12 20:36:03 +08:00
Dr_rOot 038536259e feat: add task restart icon 2019-06-12 20:34:22 +08:00
Dr_rOot ec21cc57bc Merge pull request #314 from theweavrs/patch-1
Add code of conduct for the project
2019-06-12 17:03:28 +08:00
thecodrr 5a42e4014b chore: add code of conduct for the project 2019-06-12 00:15:04 -07:00
Dr_rOot 02d4032283 fix: form-actions background color 2019-06-12 09:28:40 +08:00
Dr_rOot d676dbe213 Merge pull request #309 from theweavrs/master
feat: add background under form-actions in preferences
2019-06-12 09:08:31 +08:00
Dr_rOot 02d83534d1 refactor: check is exist before delete task file 2019-06-11 22:41:07 +08:00
Dr_rOot 8b531c76b8 fix: eslint no-empty-pattern error 2019-06-10 19:35:45 +08:00
Dr_rOot 22f92df299 fix: remove useless lab form.protocols key 2019-06-10 19:02:21 +08:00
Dr_rOot eaf91e15e8 Merge pull request #310 from agalwood/feature/protocol_setting_201906091107
feat: add option to set default protocols client #305
2019-06-10 18:34:05 +08:00
Dr_rOot 4535cb706a fix: setup-protocols-client command logic 2019-06-10 17:47:51 +08:00
Dr_rOot a093f3beca chore: i18n tw protocols 2019-06-10 17:47:12 +08:00
Dr_rOot 287c9038b1 Merge pull request #308 from theweavrs/feature/protocol_setting_201906091107
feat: add option to set default protocols
2019-06-10 17:12:25 +08:00
thecodrr 72aac9c0c6 feat: add background under form-actions 2019-06-10 01:48:20 -07:00
thecodrr cdac88371c refactor: remove change handlers 2019-06-10 00:52:30 -07:00
thecodrr 678bed53dc feat: add localization for protocol settings 2019-06-10 00:49:33 -07:00
thecodrr 1f805c3440 refactor: remove unused localized string 2019-06-10 00:22:31 -07:00
thecodrr c8dcb1023f feat: handle setup-protocols-client command 2019-06-10 00:17:55 -07:00
thecodrr a0e7eb84ca feat: send setup-protocols-client command 2019-06-10 00:03:10 -07:00
thecodrr fdf0bb8320 refactor: move protocol settings to advanced menu 2019-06-09 22:53:21 -07:00
thecodrr e2338757de refactor: merge magnet & thunder protocol handling 2019-06-09 22:07:09 -07:00
Dr_rOot c0cbfb5cb2 refactor: preferences lab protocol client settings 2019-06-10 11:35:48 +08:00
Dr_rOot fddaa72ac6 refactor: protocol manager init setup 2019-06-09 23:09:59 +08:00
Dr_rOot 1e531f166b feat: handle thunder protocol 2019-06-09 23:09:27 +08:00
Dr_rOot 97f54adc49 feat: add protocols to user config 2019-06-09 23:08:30 +08:00
Dr_rOot e6548d5548 Merge pull request #306 from agalwood/feature/rpc_secret_201906071137
feat: preferences add rpc-secret setting #138
2019-06-09 22:54:58 +08:00
Dr_rOot 137fdf2b26 fix: npm add randomatic deps 2019-06-09 22:35:41 +08:00
Dr_rOot 10ef4f7318 feat: i18n preferences rpc-secret 2019-06-09 22:33:52 +08:00
Dr_rOot bdd5e56c2a feat: preferences add rpc-secret setting 2019-06-08 22:53:13 +08:00
Dr_rOot a851ec5830 feat: add icon dice 2019-06-08 22:52:20 +08:00
Dr_rOot 2ae3642c62 feat: add check task is seeder util 2019-06-07 20:07:20 +08:00
Dr_rOot 7b41a9e1c6 docs: update scoop install guide 2019-06-06 12:38:29 +08:00
Dr_rOot 012e5ece00 Merge pull request #301 from agalwood/feature/preferences_layout_201905301105
refactor: improve preferences layout
2019-06-05 14:59:09 +08:00
Dr_rOot db8d3d1aec feat: i18n check for update messages 2019-06-05 12:27:18 +08:00
Dr_rOot 8e35dde082 feat: add check for update at preference #298
closed #298
2019-06-05 12:26:45 +08:00
Dr_rOot 5c2acf12ee feat: tray menu support disable item 2019-06-05 11:58:23 +08:00
Dr_rOot e710ccdb34 feat: add check for update to tray menu 2019-06-05 11:57:37 +08:00
Dr_rOot 5ecc08d66d refactor: clean up useless code 2019-06-04 22:05:51 +08:00
Dr_rOot e7b1a898fa feat: add task history icon 2019-06-03 19:57:04 +08:00
Dr_rOot 93acf1ba63 fix: el-progress status value for element ui 2.9.x 2019-06-02 02:22:13 +08:00
Dr_rOot 1164df87e3 fix: i18n add missing ja translates 2019-06-01 11:47:24 +08:00
Dr_rOot 71232603a5 refactor: rename updateStates to updateMenuStates 2019-06-01 11:44:55 +08:00
Dr_rOot 286013b2f0 refacotr: clean code 2019-05-31 19:42:53 +08:00
Dr_rOot a5f0236661 Merge pull request #296 from agalwood/feature/transfer_speed_setting_201905282346
fix: refactor transfer settings
2019-05-30 20:44:28 +08:00
Dr_rOot 87857eba94 refactor: move auto update setting to advanced 2019-05-30 20:43:45 +08:00
Dr_rOot 3059d1a0b7 refactor: preferences move mock ua to security 2019-05-30 15:47:45 +08:00
Dr_rOot 5029f98153 refactor: preferences form item style 2019-05-30 14:25:56 +08:00
Dr_rOot ce80af7ead fix: increase mo-speedometer z-index 2019-05-30 14:25:23 +08:00
Dr_rOot 6df52988b0 chore: i18n preferences transfer settings 2019-05-29 23:57:42 +08:00
Dr_rOot 6359c729ad fix: horizontal scrollbar height 2019-05-29 23:53:58 +08:00
Dr_rOot 04db94daa6 refactor: i18n calc form label width with locale 2019-05-29 23:50:33 +08:00
Dr_rOot d41d809f00 Merge pull request #295 from gee1k/master
fix: remove the button in the aside panel to drag and drop
2019-05-29 15:25:37 +08:00
Svend efdfae37b5 fix:remove the button in the aside panel to drag and drop 2019-05-29 14:01:30 +08:00
Dr_rOot 1a097c02e3 refactor: transfer speed setting to select options 2019-05-28 23:51:34 +08:00
Dr_rOot 0217b5573a fix: theme merge code error 2019-05-28 23:27:57 +08:00
Dr_rOot 86611604d5 Merge branch 'feature/theme_switch_lang_201905232132'
# Conflicts:
#	src/renderer/components/Preference/Advanced.vue
#	src/renderer/components/Preference/Basic.vue
2019-05-28 23:24:08 +08:00
Dr_rOot 0bd8ab3d11 Merge pull request #294 from agalwood/feature/change_global_options_201905241932
feat: change preferences without relaunch app #24 #172 #197
2019-05-28 23:14:05 +08:00
Dr_rOot e9eadb2eba feat: i18n save preferences message 2019-05-28 22:52:50 +08:00
Dr_rOot 72afd845ba fix: default enable check auto update on macOS 2019-05-28 22:35:19 +08:00
Gary Li 91670fac37 fix: updated en-US translation (#290)
* Updated translation: en-US

* Update: en-US translation
2019-05-27 22:38:58 +08:00
Dr_rOot bc14e5b287 Merge pull request #292 from jjandxa/master
feat: add transfer speed setting
2019-05-27 22:33:11 +08:00
jjandxa 2d01431e7d feat: add transfer speed setting 2019-05-26 22:13:38 +08:00
Dr_rOot 81531ef9fc feat: change preference show message 2019-05-26 19:40:13 +08:00
Dr_rOot 04126363ca refactor: change preference without relaunch app 2019-05-25 17:17:00 +08:00
Dr_rOot bcb07656b9 refactor: rename isSyncTracker to trackerSyncing 2019-05-24 19:49:34 +08:00
Dr_rOot b9cd991fd5 refactor: delayed engine client call 2019-05-24 19:45:56 +08:00
Dr_rOot 1b2b22f039 feat: api add changeGlobalOption 2019-05-24 19:45:01 +08:00
Dr_rOot 170a481d48 feat: add diffConfig util 2019-05-24 19:43:53 +08:00
Dr_rOot 48bf7c9e2e refactor: move theme switcher & lang to basic 2019-05-23 21:46:58 +08:00
Dr_rOot 03cfb013e5 docs: fix cn readme typo 2019-05-22 10:31:43 +08:00
Dr_rOot b4e23d8805 chore: add feature request cn issue template 2019-05-22 10:31:25 +08:00
Dr_rOot 43965c5740 chore: update bug report issue template 2019-05-21 10:56:50 +08:00
Dr_rOot 5c8d2e4ca4 fix: unified scrollbar style 2019-05-20 15:01:44 +08:00
Dr_rOot b51c144ace fix: i18n task code format 2019-05-20 14:58:55 +08:00
Dr_rOot feb839b7fa Merge pull request #273 from agalwood/feature/selective_torrent_201905142048
feat: torrent selective download #253 #229 #211
2019-05-19 16:09:09 +08:00
Dr_rOot fa36397afa fix: i18n add task style 2019-05-19 15:48:53 +08:00
Dr_rOot 583fe0ffe2 feat: i18n select torrent 2019-05-19 15:48:03 +08:00
Dr_rOot 8b3a5fbaa8 fix: select torrent reset 2019-05-19 15:45:39 +08:00
Dr_rOot 85493c263b fix: select torrent layout 2019-05-19 15:45:20 +08:00
Dr_rOot 78e106abe4 fix: add selective torrent list utils 2019-05-19 11:44:49 +08:00
Dr_rOot bbf90e9344 fix: torrent file list dark theme style 2019-05-19 11:44:21 +08:00
Dr_rOot dc30c25a83 refactor: select torrent to support selective 2019-05-19 11:42:47 +08:00
Dr_rOot e1cce4f50c refactor: add task to support selective torrent 2019-05-18 21:11:03 +08:00
Dr_rOot 61654ff0ff refactor: remove add task iLoveEggFeatures 2019-05-17 22:39:27 +08:00
Dr_rOot 0142aedfa5 feat: element dialog & table dark theme style 2019-05-17 23:11:24 +08:00
Dr_rOot 323f85ca40 feat: add video audio image files filter utils 2019-05-17 23:08:47 +08:00
Dr_rOot f35e696c6a feat: add file type icon 2019-05-16 20:05:13 +08:00
Dr_rOot d49cbcdc00 feat: add seed-time to system config 2019-05-16 19:54:35 +08:00
Dr_rOot c85ac4e895 feat: set bt-remove-unselected-file to true 2019-05-15 22:06:05 +08:00
Dr_rOot f831cc51ed fix: add task number input text overflow 2019-05-14 20:51:57 +08:00
Dr_rOot d47eb9ba0f refactor: subnav li style 2019-05-14 20:51:04 +08:00
Dr_rOot 119a374db6 fix: clean subnav code 2019-05-13 19:34:47 +08:00
Dr_rOot d26808e43a Merge pull request #262 from agalwood/feature/open_source_license_201905102203
feat: add open source license link to about panel
2019-05-12 11:36:34 +08:00
Dr_rOot 8cb3e54be2 fix: i18n add missing fa about license translate 2019-05-11 10:38:40 +08:00
Dr_rOot c55902cda7 fix: about pannel add license link 2019-05-10 22:33:16 +08:00
Dr_rOot 426b54201b Merge pull request #258 from agalwood/feature/keep_window_size_201905072013
feat: keep window size & position #232 #224 #48
2019-05-09 16:58:40 +08:00
Dr_rOot 6c032cde2d feat: i18n preference keep window state 2019-05-09 12:23:43 +08:00
Dr_rOot eb42ac6cfd feat: preference basic add keep window state chk 2019-05-08 11:40:49 +08:00
Dr_rOot 90f0a7c5f6 feat: restore window state at init 2019-05-08 00:04:53 +08:00
Dr_rOot 9b61dad2c3 feat: store window state 2019-05-08 00:03:25 +08:00
Dr_rOot 671fb82e6a feat: window manager emit resized, moved, closed 2019-05-07 23:56:38 +08:00
Dr_rOot b8f444ca4d fix: detect thunder resource uris add default val 2019-05-06 23:05:56 +08:00
Dr_rOot 7509442e4e refactor: thunder link tip improve 2019-05-05 12:01:11 +08:00
Dr_rOot ee2e3de782 Merge pull request #246 from agalwood/feature/auto_launch_201905031132
feat: auto open at login #164 #210 #237
2019-05-04 20:18:08 +08:00
Dr_rOot c6dd1e333e docs: add fixUserConfig comment 2019-05-04 20:02:16 +08:00
Dr_rOot fba761a29c feat: auto fix user config open-at-login value
Auto fix user config `open-at-login` value when user delete Motrix in OS startup manage
2019-05-04 11:50:51 +08:00
Dr_rOot 4fb94ae8bb fix: second instance could not restore window #233 2019-05-03 22:21:08 +08:00
Dr_rOot 79721822c2 feat: hide window when app launch at login 2019-05-03 15:40:00 +08:00
Dr_rOot 556f58f6b3 chore: i18n open at login 2019-05-03 15:39:18 +08:00
Dr_rOot e690f15335 feat: preference open at login 2019-05-03 15:20:34 +08:00
Dr_rOot 1876587973 feat: auto launch manager 2019-05-03 15:18:57 +08:00
Dr_rOot b89c651132 refactor: auto check update 2019-05-02 15:37:46 +08:00
zhtw ad9d3ed15a fix: some zh-TW typos (#242)
* Update preferences.js

* Update subnav.js

* Update task.js

* Update task.js
2019-05-01 17:54:17 +08:00
Dr_rOot 6aa362332a feat: add dir class watch 2019-05-01 17:09:49 +08:00
Dr_rOot 18d107c062 feat: detect text direction 2019-05-01 17:03:52 +08:00
Dr_rOot ebeba4663c docs: update readme 2019-04-30 21:01:05 +08:00
FloatingShuYin 9bff4257a8 docs: Add tips on how to install package management tools on Windows (#241)
* Add tips on how to install package management tools on Windows

* Remove extra spaces

* Layout revision
2019-04-30 20:16:41 +08:00
Dr_rOot e07ef7dd11 fix: bump version to 1.3.8 2019-04-29 09:49:33 +08:00
Dr_rOot ebb0926d1d fix: preference basic & lab save config fail #128
v1.3.7 btTracker.trim()
2019-04-29 09:46:52 +08:00
Dr_rOot 5333438825 fix: screenshots file name add @2x suffix 2019-04-28 17:23:28 +08:00
Dr_rOot 3664341822 docs: add app screenshots 2019-04-28 17:21:32 +08:00
Dr_rOot d3cbff6dd1 fix: preference link color in dark mode 2019-04-28 17:08:51 +08:00
Dr_rOot 5668b0773d fix: sync icon stroke color 2019-04-28 12:41:25 +08:00
Dr_rOot b757112c30 fix: update readme supported languages 2019-04-28 11:49:32 +08:00
Dr_rOot dc3a01fb3c fix: bump version to 1.3.7 2019-04-27 22:02:23 +08:00
KOZ39 591de11072 fix: Improve Korean translation (#238) 2019-04-27 21:54:46 +08:00
Dr_rOot 853c361e6d fix: bump version to 1.3.6 2019-04-27 19:37:35 +08:00
Dr_rOot b0ebc737e2 fix: i18n rename and add some keys 2019-04-27 19:36:02 +08:00
Dr_rOot bc9db25dfd fix: position of the proxy input is incorrect 2019-04-27 19:34:52 +08:00
KOZ39 08c9902759 feat: Add Korean translation (#236)
* Add Korean translation

* Fix typo
2019-04-27 18:31:10 +08:00
Nima Rasooli 8d2f52710d feat: Translated to Persian/Farsi (#235)
* Create about.js

* Rename src/shared/locales/fa-IR/about.js to src/shared/locales/fa/about.js

* Translated

* Translated

* Translated

* Translated

* Create index.js

* Translated

* Translated

* Translated

* translated

* Translated
2019-04-27 18:30:46 +08:00
Dr_rOot dd48fd79db fix: bump version to 1.3.5 2019-04-27 18:03:34 +08:00
Dr_rOot 9e7ad10309 Merge branch 'feature/bt_experience_opt_201904262310' 2019-04-27 18:02:19 +08:00
Dr_rOot 6e17102210 fix: mo protocol new-bt-task 2019-04-27 17:54:27 +08:00
Dr_rOot 5ed3b68a57 fix: handle launch argv 2019-04-27 17:31:56 +08:00
Dr_rOot a705427ce2 fix: open url in win & linux 2019-04-27 15:55:34 +08:00
Dr_rOot c37f7c73ce doc: change Manual link to github wiki 2019-04-27 12:14:05 +08:00
Dr_rOot efcf01d59b feat: handle magnet protocol 2019-04-27 12:13:02 +08:00
Dr_rOot 324b61567d fix: typo tip => tips 2019-04-26 23:57:55 +08:00
Dr_rOot d1e24fced0 fix: i18n preference bt tracker 2019-04-26 23:57:11 +08:00
Dr_rOot cb50d6709b feat: sync bt tracker from github
An updated list of public BitTorrent trackers
https://github.com/ngosang/trackerslist
2019-04-26 23:27:23 +08:00
Dr_rOot 900ac4c8d1 feat: preference advanced add bt tracker input 2019-04-26 23:19:10 +08:00
Dr_rOot 6696b0a538 refactor: move bt-tracker to config manager 2019-04-26 23:15:01 +08:00
Dr_rOot 110c83bcb8 fix: dht config optimization 2019-04-26 23:13:58 +08:00
Dr_rOot 136b4969bd chore: update readme
Add dark mode
2019-04-25 15:45:58 +08:00
weearc a901fdd2b6 docs: readme added linux installation guide (#228)
* add aur helper command in readme

* add aur helper command in readme
2019-04-25 15:07:56 +08:00
Dr_rOot 215bdbc416 fix: prepare for electron 5.0.x
Set webPreferences nodeIntegration to true
2019-04-25 10:53:25 +08:00
Dr_rOot 4e8d226460 fix: optimized for small screen users #48 #224 2019-04-25 10:16:16 +08:00
Dr_rOot 23f3357d27 fix: bump version to 1.3.3 2019-04-24 21:56:38 +08:00
Dr_rOot 7adafab7fe fix: i18n ja 2019-04-24 21:55:39 +08:00
HBKRKZK e3afb14e4a feat: Add Japanese language translation (#225)
* Create darwin.json

* Add files via upload

* Create about.js

* Add files via upload

* Update all.js

* Update app.js

* Update index.js

* fix

* fix preferences.js
2019-04-24 21:48:41 +08:00
Dr_rOot 228cd1fa7d fix: bump version to 1.3.2 2019-04-24 16:29:41 +08:00
Dr_rOot 47a7464bf9 doc: update translation guide 2019-04-24 16:28:04 +08:00
Dr_rOot 8efd86af3d feat: remove similar unuse config key 2019-04-24 11:35:31 +08:00
Dr_rOot ee78ae262e fix: bump version v1.3.1 2019-04-24 10:22:52 +08:00
Dr_rOot 7562f6a7d1 fix: downgrade electron-store 2019-04-24 10:22:32 +08:00
Dr_rOot defacd50e8 fix: build script —experimental-worker 2019-04-24 00:06:01 +08:00
Dr_rOot f5ed0d89cc fix: bump version to 1.3.x 2019-04-23 23:47:14 +08:00
Dr_rOot a3bb1c7ff1 Merge branch 'feature/dark_mode_201904201437' 2019-04-23 23:43:04 +08:00
Dr_rOot d0085b295d refactor: bt complete show seeding tips #179 #134 2019-04-23 23:40:01 +08:00
Dr_rOot 6cb278fd9e chore: manual update tracker 2019-04-23 18:14:50 +08:00
Dr_rOot aeeb9813ed refactor: lint fix 2019-04-23 17:56:45 +08:00
Dr_rOot 359da895e7 fix: migration electron-log from v2 to v3 2019-04-23 17:23:52 +08:00
Dr_rOot 8a3f510c38 refactor: check pid is running before kill it 2019-04-23 17:22:57 +08:00
Dr_rOot 1345994402 feat: add config schema valid 2019-04-23 17:21:56 +08:00
Dr_rOot c770108a6c refactor: electron store sort config key 2019-04-23 17:21:27 +08:00
Dr_rOot 178f2103f1 fix: destroy tray when app exit 2019-04-23 10:41:11 +08:00
Dr_rOot d5c71b50e8 fix: change application module init order 2019-04-23 10:40:30 +08:00
Dr_rOot ce09e76ffb refactor: theme style improve 2019-04-23 10:38:44 +08:00
Dr_rOot 4688b521fa fix: trim after split task link text rows #221
closed #221
2019-04-22 20:52:33 +08:00
Dr_rOot 33960dc264 fix: decrease theme switcher theme text font size 2019-04-22 20:49:15 +08:00
Dr_rOot d29d0d3321 fix: add task dialog background color 2019-04-22 15:42:09 +08:00
Dr_rOot f4c3e7be69 feat: preference advanced add theme switcher 2019-04-22 15:17:48 +08:00
Dr_rOot 338b51975c feat: preference theme switcher i18n 2019-04-22 15:17:23 +08:00
Dr_rOot e1a287350d feat: add preference theme thumb 2019-04-22 15:16:53 +08:00
Dr_rOot afeee1fc86 fix: change theme config 2019-04-21 23:42:52 +08:00
Dr_rOot a39820f8ab refactor: app style 2019-04-21 22:29:27 +08:00
Dr_rOot aea604278c fix: copyright link color 2019-04-21 22:28:40 +08:00
Dr_rOot 0b92e6b96e fix: app info style 2019-04-21 22:28:19 +08:00
Dr_rOot 2ba0040bdd feat: title bar close btn 2019-04-21 22:28:01 +08:00
Dr_rOot 04bf2b6b9d fix: logo svg fill 2019-04-21 22:26:36 +08:00
Dr_rOot cc367f4c5c fix: change show in folder icon size 2019-04-21 22:24:40 +08:00
Dr_rOot 73809a6501 refactor: app theme & add dark theme 2019-04-21 22:23:39 +08:00
Dr_rOot 5067ad7306 feat: app ui respond to system theme changed 2019-04-21 21:36:37 +08:00
Dr_rOot d5b3ad5933 fix: tray icon adapts to the dark mode #206 #207
close #206
close #207
2019-04-21 21:30:07 +08:00
Dr_rOot 7a903e112c feat: theme manager 2019-04-21 21:26:45 +08:00
Dr_rOot 829eb83a4c fix: get task full path error when file path empty 2019-04-17 15:45:20 +08:00
Dr_rOot 886acc2486 fix: thunder link decoding error #201 #209
close #209
2019-04-17 15:12:13 +08:00
Dr_rOot 87440701ab fix: block some ui text selections when drag app 2019-04-10 21:11:10 +08:00
Dr_rOot e880430e3a fix: html tpl 2019-04-07 13:31:00 +08:00
Dr_rOot 2febff883b fix: add missing auto check update TR translation 2019-04-01 21:11:07 +08:00
Bo Yuan 7d8bb443b8 feat: preferences add auto check updates setting
* add auto check update, time out: 1 min.

* fix: add auto check update, check interval: 30 min.

* no message

* no message

* fix: modify update check interval to 7 days, add display of [last check update time] to preference.

* no message

* fix: modified the group of auto-check-update, fix the display of last-check-update-time

* no message

* fix: hide last-check-update-time when never check.
2019-04-01 20:55:30 +08:00
Dr_rOot 1489d58a63 chore: rebuild snap for snapcraft 2019-03-31 11:45:54 +08:00
Dr_rOot 00fdafe824 fix: upgrade electron-builder 2019-03-30 11:46:55 +08:00
Dr_rOot 81c91e8cb1 fix: update readme badges 2019-03-28 22:58:28 +08:00
Dr_rOot 0fd34254de chore: add latest release badge 2019-03-26 20:58:22 +08:00
Dr_rOot d9298f0d46 fix: read me typo 2019-03-25 00:15:34 +08:00
Dr_rOot 83e12a699e docs: update readme add new feature 2019-03-24 21:54:28 +08:00
Dr_rOot 83b55b806d fix: bump version to 1.2.2 2019-03-24 20:44:30 +08:00
Dr_rOot d4dab6de9b fix: linux parse argv 2019-03-24 20:43:23 +08:00
Dr_rOot deae5e8e33 fix: bump version 2019-03-24 10:42:34 +08:00
Dr_rOot b098c8c9bc fix: open file argv path undefined 2019-03-24 10:42:05 +08:00
Dr_rOot b12553cc45 fix: try to fix linux read file eof 2019-03-23 18:15:13 +08:00
Dr_rOot 8891b9a79c refactor: windows tray icon changed to png 2019-03-23 16:12:27 +08:00
Dr_rOot a44f088139 fix: try to downgrade electron-builder 2019-03-22 23:45:47 +08:00
Dr_rOot 7ea0cd3e75 fix: fileAssociations for AppImage 2019-03-22 22:16:29 +08:00
Dr_rOot c93cc9d23b fix: remove node from devDependencies 2019-03-22 22:02:21 +08:00
Dr_rOot 8d2e14486d fix: remove npm audit fix 2019-03-22 21:56:14 +08:00
Dr_rOot 3775da5e36 Merge branch 'hotfix/main_refactor_201903151054' 2019-03-22 21:50:40 +08:00
Dr_rOot 2e21285f99 fix: update dependencies 2019-03-22 21:49:23 +08:00
Dr_rOot 6c2dde8e59 chore: try add npm audit fix to ci shell 2019-03-22 21:47:58 +08:00
Dr_rOot e014580512 feat: update tray icon based on changes in the download status 2019-03-22 21:45:11 +08:00
Dr_rOot e970a51b71 refactor: remove unuse menu config json 2019-03-21 18:23:07 +08:00
Antoine Leblanc 019f8be306 fix: i18n fr in preferences (#152) 2019-03-21 11:10:39 +08:00
Dr_rOot 20f79dacb7 refactor: menu i18n 2019-03-20 23:22:48 +08:00
Dr_rOot 1bdd17a80a feat: add tray 2019-03-20 23:18:30 +08:00
Dr_rOot b01e006073 refactor: window close event 2019-03-20 22:57:31 +08:00
Dr_rOot 82728a2b23 refactor: windows manager show hide 2019-03-20 22:55:37 +08:00
Dr_rOot 217d2df5be fix: open-file dialog cancel 2019-03-20 21:10:02 +08:00
Dr_rOot 960f0674ef fix: open url send command to all 2019-03-19 23:17:53 +08:00
Dr_rOot 54e9f326d9 refactor: return change language promise 2019-03-19 23:16:41 +08:00
Dr_rOot 4e7267028f fix: sendCommandToAll fn typo 2019-03-19 23:14:58 +08:00
Dr_rOot efd7f97a36 fix: add open-file to task i18n file 2019-03-19 23:13:04 +08:00
Dr_rOot 5bb790822d fix: mac dock download speed text add /s 2019-03-19 18:30:19 +08:00
Dr_rOot 71f3fb601b fix: send command no effect when no focused window 2019-03-19 18:29:35 +08:00
Dr_rOot af710aa265 refactor: rename handleFileAssociation 2019-03-19 18:05:20 +08:00
Dr_rOot 52b6fb0849 fix: add pt menu missing translations 2019-03-17 12:09:06 +08:00
Dr_rOot b8d63374b7 fix: add fr menu missing translations 2019-03-17 11:50:19 +08:00
Dr_rOot ff38d4ea5c refactor: main index to launcher 2019-03-17 11:36:18 +08:00
Dr_rOot a24a7acfaf feat: add support for windows x86 2019-03-17 11:34:44 +08:00
Dr_rOot 16e9c8d848 feat: add torrent to file associations 2019-03-17 11:33:44 +08:00
Dr_rOot f36cdccf9f feat: open torrent from file dialog 2019-03-17 11:31:54 +08:00
Dr_rOot c826a7dd77 fix: on download pause message 2019-03-17 11:20:22 +08:00
Dr_rOot b96518a42c fix: remove task confirm message typo 2019-03-17 10:54:41 +08:00
Dr_rOot 02f0b66500 fix: select torrent counld not replace 2019-03-17 10:54:12 +08:00
Dr_rOot 377bc47d87 refactor: engine fetchTaskItem 2019-03-17 00:29:18 +08:00
Dr_rOot f8a4ef267d fix: i18n startEngine error message 2019-03-17 00:27:52 +08:00
Dr_rOot baea3f0345 refactor: task removeTask action 2019-03-16 21:26:52 +08:00
Dr_rOot 1fcf0bb0d0 fix: main i18n #120
close #120
2019-03-16 16:11:10 +08:00
Dr_rOot 85e1acfe5b chore: config manager add doc link comment 2019-03-16 16:07:05 +08:00
Dr_rOot 41ac6ad335 fix: add missing translations 2019-03-16 16:05:15 +08:00
Dr_rOot b151c45e70 fix: remove useless page configuration 2019-03-16 16:04:06 +08:00
Dr_rOot b3686fff04 fix: torrent dragger on drop 2019-03-15 23:32:58 +08:00
Dr_rOot af81107b3d fix: temp set max-overall-upload-limit=128K #136
Preferences will be added to the speed limit setting.
close #136
2019-03-14 21:24:08 +08:00
Dr_rOot 88224998b7 fix: readme link 2019-03-14 21:03:18 +08:00
Dr_rOot 8508ca9b3c fix: i18n pt-BR 2019-03-14 21:01:38 +08:00
Dr_rOot 6fad6a876c chore: update readme i18n progress 2019-03-14 20:59:14 +08:00
Dr_rOot 6c8a844cd9 fix: copyright left & right width 2019-03-14 20:47:52 +08:00
Schlömi 4657a503f9 feat: added german (#140)
* added german

* Improved german

* more details for preferences.continue

* shorted some translations, added missing seperator
2019-03-14 20:46:14 +08:00
Dr_rOot 324347e591 fix: menu task.clear-recent-tasks no effect #135
close #135
2019-03-10 15:28:53 +08:00
Kay 16c376c108 refactor: drag and drop file (#124)
* add drag file

* refactor: drag and drop file

* add template
2019-03-10 10:47:57 +08:00
monomagentaeggroll 79cad28cc1 fix: README.md editing (#123)
* Update README.md

Revision sweep of the README.md file.
Some style changes, fixes a few typos, and corrects some grammar.

* Update README.md
2019-03-04 20:52:22 +08:00
Dr_rOot ac16bd91c2 fix: i18n pt explanation 2019-03-03 19:43:21 +08:00
Dr_rOot fafeaca47d chore: update bug_report_cn issue template 2019-03-03 19:36:07 +08:00
Dr_rOot 3152252fb8 refactor: i18n sort locale key 2019-03-03 19:25:53 +08:00
FramboisePi a5240bfeb0 fix: French spelling improvement (#117)
* Accents correction

* French: accent improvement in edit.js

* French: accent improvement in help.js

* French: accent improvement in menu.js

* French spelling improvement in preferences.js

* French spelling improvement in task.js
2019-03-03 19:24:25 +08:00
Andre Noberto 64cda63587 feat: Adding the Brazilian portuguese translation to the app [Done] (#111)
* Added locales for pt-BR

* Added menu support for pt-BR

* Configuring pt-BR in locales

* Fixing typo

* Make use of abbreviation

* Fixed typo & adjustments on variable naming case
2019-03-03 18:34:38 +08:00
Dr_rOot fe071a3783 fix: temp limit the task list num 2019-03-01 22:25:14 +08:00
Dr_rOot 5d812e9c4e fix: readme typo 2019-03-01 22:07:25 +08:00
Dr_rOot f36ba605e2 fix: update readme 2019-03-01 21:32:26 +08:00
Dr_rOot e7ed58e394 fix: i18n for some reason 2019-03-01 21:27:44 +08:00
Dr_rOot be789e7ea8 Merge pull request #108 from Yukaii/locale-zh-tw
feat: Add zh-TW language support
2019-03-01 20:44:08 +08:00
Yukai Huang 780a01e404 feat: Adding zh-TW language support 2019-03-01 14:51:04 +08:00
Dr_rOot b45518a5b6 fix: increase engine retry max to 10 2019-02-28 13:17:12 +08:00
Dr_rOot 2401d68a24 fix: add missing brew cask cmd 2019-02-28 13:16:36 +08:00
Dr_rOot 6cb2986f39 style: readme adjust the paragraph 2019-02-28 13:03:53 +08:00
Dr_rOot cb8e0dbd2e refactor: advanced preference change lng 2019-02-28 13:01:03 +08:00
Dr_rOot b4faed0621 docs: update readme 2019-02-28 12:59:55 +08:00
Dr_rOot 249aa616fe Merge pull request #101 from gpatarin/master
feat: Adding the french translation to the app [Done]
2019-02-28 12:57:52 +08:00
Gael Patarin 482ccb3293 Update utils.js to match latest changes 2019-02-27 23:33:21 +01:00
Gael Patarin f1be6bc1a4 Translated the app to french 2019-02-27 19:52:56 +01:00
Dr_rOot 326e8c700b fix: update i18n progress 2019-02-27 21:13:57 +08:00
Dr_rOot 2a538fd7c3 fix: getTaskFullPath bittorrent 2019-02-27 21:07:00 +08:00
Dr_rOot c424b981b3 Merge pull request #97 from agalwood/revert-93-master
fix: Revert "feat: Adding the french translation to the app [WIP]"
2019-02-27 21:05:26 +08:00
Dr_rOot a284aba2cc Revert "feat: Adding the french translation to the app [WIP]" 2019-02-27 20:54:07 +08:00
Dr_rOot c8bfdbf087 Merge pull request #93 from gpatarin/master
feat: Adding the french translation to the app [WIP]
2019-02-27 20:47:49 +08:00
Gael Patarin eb80f3698f More translation in french (WIP) 2019-02-26 19:18:55 +01:00
Gael Patarin 23f3d85ad4 Added french translation 2019-02-26 19:13:28 +01:00
Dr_rOot 24019123ba fix: add i18n guide link to readme 2019-02-25 23:48:56 +08:00
Dr_rOot 06a471982a fix: add CONTRIBUTING Guide 2019-02-25 23:46:24 +08:00
Dr_rOot 43627aba50 fix: linux AppImage dock icon missing #83
Close #83
2019-02-25 19:33:23 +08:00
Dr_rOot 8116234b3e fix: update npm dependencies 2019-02-24 15:21:45 +08:00
Dr_rOot e488de5c3f fix: magnet link task moveTaskFilesToTrash bug 2019-02-24 15:05:19 +08:00
Dr_rOot 084f834a41 fix: update readme 2019-02-24 13:33:18 +08:00
Dr_rOot 97d30ee85e fix: update bug report issue template 2019-02-24 13:05:32 +08:00
Dr_rOot 387ccc9cf7 fix: i18n download-session-path error 2019-02-23 18:32:50 +08:00
Dr_rOot fed5744607 docs: update github issue template 2019-02-21 12:56:30 +08:00
Dr_rOot 3e2b448e09 fix: openDownloadDock & updateDockBadge mac only 2019-02-20 18:05:43 +08:00
Dr_rOot c12c13066d fix: magnet task file path did not start with dir 2019-02-20 12:54:51 +08:00
Dr_rOot 5c36454ca0 fix: copy link fail when bttorrent info is empty 2019-02-20 12:54:17 +08:00
Dr_rOot 7b6ba13d94 fix: eslint 2019-02-19 20:52:03 +08:00
Dr_rOot 5d93d4d7bb fix: bt task copy link bug #39
Close #39
2019-02-19 20:50:36 +08:00
Dr_rOot 4d024eb6a6 feat: fetch engineOptions (getGlobalOption) 2019-02-19 20:48:39 +08:00
Dr_rOot 182acec265 fix: remove task with file name is empty bug #75 2019-02-18 22:54:05 +08:00
Dr_rOot e293b16343 fix: one msg notify twice error 2019-02-18 22:29:39 +08:00
Dr_rOot 70cf36d7b2 Merge pull request #73 from Raistlin916/master
refactor: message refactor
2019-02-18 21:33:57 +08:00
Kay f3d8cac9ba fix: update .editorconfig 2019-02-18 21:24:03 +08:00
Dr_rOot 620b243794 Merge pull request #72 from mesquka/master
fix: Consistant hms capitalisation
2019-02-18 11:46:08 +08:00
gaokai 37fe7d4dbd feat: msg add max length with queue 2019-02-18 01:05:25 +08:00
gaokai 11b6d651b8 refactor: message default options 2019-02-18 00:36:21 +08:00
Kieran Mesquita 8a5bc11d88 Merge remote-tracking branch 'upstream/master' 2019-02-17 23:07:24 +08:00
Kieran Mesquita bf69146035 Decapitalise 'h' for hms consistancy 2019-02-17 23:06:43 +08:00
Dr_rOot 14ff0c4bbe fix: add preferences missing translations 2019-02-17 11:02:29 +08:00
Dr_rOot d9706a2c3e Merge pull request #70 from abdullah/improve-tr-localization-key
refactor: rename Turkish i18n key from 'Tr-tr' to 'tr'
2019-02-17 10:57:58 +08:00
Abdullah mara c36f7b73f1 refactor: rename Turkish i18n key from 'Tr-tr' to 'tr'
This commit also includes menu localization keys.
2019-02-16 21:06:20 +03:00
Dr_rOot 7e6d0542cc fix: update readme 2019-02-16 23:11:12 +08:00
Dr_rOot 72bf4ec909 style: update i18n 2019-02-16 23:09:40 +08:00
Dr_rOot fa87b8ff9b fix: i18n hash link 2019-02-16 23:07:38 +08:00
Dr_rOot 31203e72fc fix: update README i18n 2019-02-16 23:06:07 +08:00
Dr_rOot 5bd9875f61 Merge pull request #67 from abdullah/add-turkish
feat: Add Turkish.
2019-02-16 21:56:54 +08:00
Abdullah mara 646ad28fbc Add Turkish. 2019-02-16 16:30:51 +03:00
Dr_rOot a66d482d3a fix: aside draggable area not response click event 2019-02-16 19:45:59 +08:00
Dr_rOot 5dfc8cce37 Merge pull request #63 from mesquka/master
feat: Make notifications dismissible and truncate long messages
2019-02-16 10:28:16 +08:00
Kieran Mesquita 4c88431147 Make all message notifications dismissable 2019-02-16 02:49:04 +08:00
Dr_rOot bb06b3970d refactor: util getTaskName 2019-02-15 23:48:26 +08:00
Dr_rOot c86767bc3f fix: el message text style 2019-02-15 23:44:17 +08:00
Dr_rOot 3c6d14ec7e Merge pull request #59 from mesquka/master
fix: Form Labels in add Task
2019-02-15 14:13:11 +08:00
Kieran Mesquita 88a9a69c27 Adjust width of add task labels to fit 'user-agent' 2019-02-15 13:52:02 +08:00
Kieran Mesquita da7241cd6a Fix Form Labels 2019-02-15 13:44:10 +08:00
Dr_rOot 397055826e Merge pull request #57 from Raistlin916/master
feat: drag & drop torrent file to add task
2019-02-15 11:54:31 +08:00
raistlin916 2e6b8bb5fa add drag file 2019-02-15 10:57:04 +08:00
Dr_rOot ed4f3afcbd fix: update app screenshot 2019-02-14 21:35:47 +08:00
Dr_rOot 53ab75fbf9 fix: update hide app menu default 2019-02-14 21:20:33 +08:00
Dr_rOot c19cf17b07 fix: update read me 2019-02-14 17:23:54 +08:00
Dr_rOot a994f45e8f fix: add manual link to readme 2019-02-14 13:28:24 +08:00
Dr_rOot 1bdaeeb3a6 fix: Windows title bar drag 2019-02-13 12:08:18 +08:00
Dr_rOot 32f0a3d084 fix: windows &linux hide app menu fail 2019-02-12 23:25:24 +08:00
Dr_rOot ba4ef326f7 feat: add lock bot config 2019-02-11 21:57:42 +08:00
Dr_rOot 10a8f0bd16 fix: remove pacman && update version to 1.1.3 2019-02-10 23:14:47 +08:00
440 changed files with 28618 additions and 24961 deletions
+7 -17
View File
@@ -2,19 +2,11 @@
"comments": false,
"env": {
"main": {
"presets": [
["env", {
"targets": { "node": 7 }
}],
"stage-0"
]
"presets": ["@babel/preset-env"]
},
"renderer": {
"presets": [
["env", {
"modules": false
}],
"stage-0"
"@babel/preset-env"
],
"plugins": [
[
@@ -27,12 +19,7 @@
]
},
"web": {
"presets": [
["env", {
"modules": false
}],
"stage-0"
],
"presets": ["@babel/preset-env"],
"plugins": [
[
"component",
@@ -44,5 +31,8 @@
]
}
},
"plugins": ["transform-runtime"]
"plugins": [
"@babel/plugin-proposal-class-properties",
"@babel/plugin-transform-runtime"
]
}
+8
View File
@@ -0,0 +1,8 @@
root = true
[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
+13 -9
View File
@@ -7,8 +7,7 @@ const chalk = require('chalk')
const del = require('del')
const { spawn } = require('child_process')
const webpack = require('webpack')
const Multispinner = require('multispinner')
const Multispinner = require('@motrix/multispinner')
const mainConfig = require('./webpack.main.config')
const rendererConfig = require('./webpack.renderer.config')
@@ -19,12 +18,16 @@ const errorLog = chalk.bgRed.white(' ERROR ') + ' '
const okayLog = chalk.bgBlue.white(' OKAY ') + ' '
const isCI = process.env.CI || false
if (process.env.BUILD_TARGET === 'clean') clean()
else if (process.env.BUILD_TARGET === 'web') web()
else build()
if (process.env.BUILD_TARGET === 'clean') {
clean()
} else if (process.env.BUILD_TARGET === 'web') {
web()
} else {
build()
}
function clean () {
del.sync(['build/*', '!build/icons', '!build/icons/icon.*'])
del.sync(['release/*', '!.gitkeep'])
console.log(`\n${doneLog}\n`)
process.exit()
}
@@ -74,8 +77,9 @@ function pack (config) {
return new Promise((resolve, reject) => {
config.mode = 'production'
webpack(config, (err, stats) => {
if (err) reject(err.stack || err)
else if (stats.hasErrors()) {
if (err) {
reject(err.stack || err)
} else if (stats.hasErrors()) {
let err = ''
stats.toString({
@@ -129,4 +133,4 @@ function greeting () {
})
} else console.log(chalk.yellow.bold('\n lets-build'))
console.log()
}
}
+2 -1
View File
@@ -8,6 +8,7 @@ const { spawn } = require('child_process')
const webpack = require('webpack')
const WebpackDevServer = require('webpack-dev-server')
const webpackHotMiddleware = require('webpack-hot-middleware')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const mainConfig = require('./webpack.main.config')
const rendererConfig = require('./webpack.renderer.config')
@@ -49,7 +50,7 @@ function startRenderer () {
})
compiler.hooks.compilation.tap('compilation', compilation => {
compilation.hooks.htmlWebpackPluginAfterEmit.tapAsync('html-webpack-plugin-after-emit', (data, cb) => {
HtmlWebpackPlugin.getHooks(compilation).afterEmit.tapAsync('html-webpack-plugin-after-emit', (data, cb) => {
hotMiddleware.publish({ action: 'reload' })
cb()
})
+15 -16
View File
@@ -6,8 +6,8 @@ const devMode = process.env.NODE_ENV !== 'production'
const path = require('path')
const { dependencies, build } = require('../package.json')
const webpack = require('webpack')
const BabiliWebpackPlugin = require('babili-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin');
const ESLintPlugin = require('eslint-webpack-plugin');
let mainConfig = {
entry: {
@@ -18,17 +18,6 @@ let mainConfig = {
],
module: {
rules: [
{
test: /\.(js)$/,
enforce: 'pre',
exclude: /node_modules/,
use: {
loader: 'eslint-loader',
options: {
formatter: require('eslint-friendly-formatter')
}
}
},
{
test: /\.js$/,
use: 'babel-loader',
@@ -50,7 +39,10 @@ let mainConfig = {
path: path.join(__dirname, '../dist/electron')
},
plugins: [
new webpack.NoEmitOnErrorsPlugin()
new webpack.NoEmitOnErrorsPlugin(),
new ESLintPlugin({
formatter: require('eslint-friendly-formatter')
})
],
resolve: {
alias: {
@@ -59,7 +51,15 @@ let mainConfig = {
},
extensions: ['.js', '.json', '.node']
},
target: 'electron-main'
target: 'electron-main',
optimization: {
minimize: !devMode,
minimizer: [
new TerserPlugin({
extractComments: false,
})
],
},
}
/**
@@ -79,7 +79,6 @@ if (devMode) {
*/
if (!devMode) {
mainConfig.plugins.push(
new BabiliWebpackPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"production"',
'appId': `"${build.appId}"`
+45 -38
View File
@@ -6,13 +6,13 @@ const devMode = process.env.NODE_ENV !== 'production'
const path = require('path')
const { dependencies } = require('../package.json')
const webpack = require('webpack')
const BabiliWebpackPlugin = require('babili-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const ESLintPlugin = require('eslint-webpack-plugin');
/**
* List of node_modules to include in webpack bundle
@@ -24,7 +24,6 @@ const { VueLoaderPlugin } = require('vue-loader')
let whiteListedModules = ['vue']
let rendererConfig = {
devtool: '#cheap-module-eval-source-map',
entry: {
index: path.join(__dirname, '../src/renderer/pages/index/main.js')
},
@@ -34,14 +33,10 @@ let rendererConfig = {
module: {
rules: [
{
test: /\.(js|vue)$/,
enforce: 'pre',
exclude: /node_modules/,
test: /\.worker\.js$/,
use: {
loader: 'eslint-loader',
options: {
formatter: require('eslint-friendly-formatter')
}
loader: 'worker-loader',
options: { filename: '[name].js' }
}
},
{
@@ -52,8 +47,11 @@ let rendererConfig = {
{
loader: 'sass-loader',
options: {
data: '@import "@/components/Theme/Variables.scss";',
includePaths:[__dirname, 'src']
implementation: require('sass'),
additionalData: '@import "@/components/Theme/Variables.scss";',
sassOptions: {
includePaths:[__dirname, 'src']
}
},
}
]
@@ -66,9 +64,12 @@ let rendererConfig = {
{
loader: 'sass-loader',
options: {
implementation: require('sass'),
indentedSyntax: true,
data: '@import "@/components/Theme/Variables.scss";',
includePaths:[__dirname, 'src']
additionalData: '@import "@/components/Theme/Variables.scss";',
sassOptions: {
includePaths:[__dirname, 'src']
}
},
}
]
@@ -88,10 +89,6 @@ let rendererConfig = {
'css-loader'
]
},
{
test: /\.html$/,
use: 'vue-html-loader'
},
{
test: /\.js$/,
use: 'babel-loader',
@@ -119,7 +116,7 @@ let rendererConfig = {
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use: {
loader: 'url-loader',
query: {
options: {
limit: 10000,
name: 'imgs/[name]--[folder].[ext]'
}
@@ -137,7 +134,7 @@ let rendererConfig = {
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
use: {
loader: 'url-loader',
query: {
options: {
limit: 10000,
name: 'fonts/[name]--[folder].[ext]'
}
@@ -155,12 +152,6 @@ let rendererConfig = {
filename: '[name].css',
chunkFilename: '[id].css'
}),
new OptimizeCSSPlugin({
cssProcessorOptions: {
safe: true,
discardComments: { removeAll: true }
}
}),
new HtmlWebpackPlugin({
title: 'Motrix',
filename: 'index.html',
@@ -171,17 +162,25 @@ let rendererConfig = {
// removeAttributeQuotes: true,
// removeComments: true
// },
isBrowser: false,
isDev: process.env.NODE_ENV !== 'production',
nodeModules: devMode
? path.resolve(__dirname, '../node_modules')
: false
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
new webpack.NoEmitOnErrorsPlugin(),
new ESLintPlugin({
extensions: ['js', 'vue'],
formatter: require('eslint-friendly-formatter')
})
],
output: {
filename: '[name].js',
libraryTarget: 'commonjs2',
path: path.join(__dirname, '../dist/electron')
path: path.join(__dirname, '../dist/electron'),
globalObject: 'this',
publicPath: ''
},
resolve: {
alias: {
@@ -191,13 +190,24 @@ let rendererConfig = {
},
extensions: ['.js', '.vue', '.json', '.css', '.node']
},
target: 'electron-renderer'
target: 'electron-renderer',
optimization: {
minimize: !devMode,
minimizer: [
new TerserPlugin({
extractComments: false,
}),
new CssMinimizerPlugin(),
],
},
}
/**
* Adjust rendererConfig for development settings
*/
if (devMode) {
rendererConfig.devtool = 'eval-cheap-module-source-map'
rendererConfig.plugins.push(
new webpack.DefinePlugin({
'__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"`
@@ -209,17 +219,14 @@ if (devMode) {
* Adjust rendererConfig for production settings
*/
if (!devMode) {
rendererConfig.devtool = ''
rendererConfig.plugins.push(
new BabiliWebpackPlugin(),
new CopyWebpackPlugin([
{
new CopyWebpackPlugin({
patterns: [{
from: path.join(__dirname, '../static'),
to: path.join(__dirname, '../dist/electron/static'),
ignore: ['.*']
}
]),
globOptions: { ignore: [ '.*' ] }
}]
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"production"'
}),
+62 -47
View File
@@ -6,13 +6,13 @@ const devMode = process.env.NODE_ENV !== 'production'
const path = require('path')
const { dependencies } = require('../package.json')
const webpack = require('webpack')
const BabiliWebpackPlugin = require('babili-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const ESLintPlugin = require('eslint-webpack-plugin');
/**
* List of node_modules to include in webpack bundle
@@ -24,7 +24,6 @@ const { VueLoaderPlugin } = require('vue-loader')
let whiteListedModules = ['vue']
let webConfig = {
devtool: '#cheap-module-eval-source-map',
entry: {
index: path.join(__dirname, '../src/renderer/pages/index/main.js')
},
@@ -34,14 +33,10 @@ let webConfig = {
module: {
rules: [
{
test: /\.(js|vue)$/,
enforce: 'pre',
exclude: /node_modules/,
test: /\.worker\.js$/,
use: {
loader: 'eslint-loader',
options: {
formatter: require('eslint-friendly-formatter')
}
loader: 'worker-loader',
options: { filename: '[name].js' }
}
},
{
@@ -49,7 +44,16 @@ let webConfig = {
use: [
devMode ? 'vue-style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
{
loader: 'sass-loader',
options: {
implementation: require('sass'),
additionalData: '@import "@/components/Theme/Variables.scss";',
sassOptions: {
includePaths:[__dirname, 'src']
}
},
}
]
},
{
@@ -57,7 +61,17 @@ let webConfig = {
use: [
devMode ? 'vue-style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader?indentedSyntax'
{
loader: 'sass-loader',
options: {
implementation: require('sass'),
indentedSyntax: true,
additionalData: '@import "@/components/Theme/Variables.scss";',
sassOptions: {
includePaths:[__dirname, 'src']
}
},
}
]
},
{
@@ -99,7 +113,7 @@ let webConfig = {
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use: {
loader: 'url-loader',
query: {
options: {
limit: 10000,
name: 'imgs/[name].[ext]'
}
@@ -109,7 +123,7 @@ let webConfig = {
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
use: {
loader: 'url-loader',
query: {
options: {
limit: 10000,
name: 'fonts/[name].[ext]'
}
@@ -123,12 +137,6 @@ let webConfig = {
filename: '[name].css',
chunkFilename: '[id].css'
}),
new OptimizeCSSPlugin({
cssProcessorOptions: {
safe: true,
discardComments: { removeAll: true }
}
}),
new HtmlWebpackPlugin({
title: 'Motrix',
filename: 'index.html',
@@ -139,20 +147,8 @@ let webConfig = {
// removeAttributeQuotes: true,
// removeComments: true
// },
nodeModules: devMode
? path.resolve(__dirname, '../node_modules')
: false
}),
new HtmlWebpackPlugin({
title: '关于',
filename: 'about.html',
chunks: ['about'],
template: path.resolve(__dirname, '../src/about.ejs'),
// minify: {
// collapseWhitespace: true,
// removeAttributeQuotes: true,
// removeComments: true
// },
isBrowser: true,
isDev: process.env.NODE_ENV !== 'production',
nodeModules: devMode
? path.resolve(__dirname, '../node_modules')
: false
@@ -161,11 +157,17 @@ let webConfig = {
'process.env.IS_WEB': 'true'
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
new webpack.NoEmitOnErrorsPlugin(),
new ESLintPlugin({
extensions: ['js', 'vue'],
formatter: require('eslint-friendly-formatter')
})
],
output: {
filename: '[name].js',
path: path.join(__dirname, '../dist/web')
path: path.join(__dirname, '../dist/web'),
globalObject: 'this',
publicPath: ''
},
resolve: {
alias: {
@@ -175,24 +177,37 @@ let webConfig = {
},
extensions: ['.js', '.vue', '.json', '.css']
},
target: 'web'
target: 'web',
optimization: {
minimize: !devMode,
minimizer: [
new TerserPlugin({
extractComments: false,
}),
new CssMinimizerPlugin(),
],
},
}
/**
* Adjust webConfig for development settings
*/
if (devMode) {
webConfig.devtool = 'eval-cheap-module-source-map'
}
/**
* Adjust webConfig for production settings
*/
if (!devMode) {
webConfig.devtool = ''
webConfig.plugins.push(
new BabiliWebpackPlugin(),
new CopyWebpackPlugin([
{
new CopyWebpackPlugin({
patterns: [{
from: path.join(__dirname, '../static'),
to: path.join(__dirname, '../dist/web/static'),
ignore: ['.*']
}
]),
to: path.join(__dirname, '../dist/electron/static'),
globOptions: { ignore: [ '.*' ] }
}]
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"production"'
}),
+7
View File
@@ -0,0 +1,7 @@
src/renderer/components/Icons/*.js
src/shared/locales/*
!src/shared/locales/all.js
!src/shared/locales/app.js
!src/shared/locales/index.js
!src/shared/locales/LocalManager.js
+24 -17
View File
@@ -1,27 +1,34 @@
module.exports = {
root: true,
parser: 'babel-eslint',
parserOptions: {
sourceType: 'module'
},
env: {
browser: true,
node: true
},
extends: 'standard',
extends: [
'plugin:vue/essential',
'@vue/standard'
],
parserOptions: {
parser: 'babel-eslint'
},
globals: {
appId: true,
__static: true
},
plugins: [
'html'
],
'rules': {
// allow paren-less arrow functions
'arrow-parens': 0,
// allow async-await
'generator-star-spacing': 0,
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
}
}
rules: {
'no-console': 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'indent': ['error', 2],
'vue/script-indent': ['error', 2, {
'baseIndent': 1
}],
},
overrides: [
{
'files': ['*.vue'],
'rules': {
'indent': 'off'
}
}
]
};
+12 -7
View File
@@ -2,11 +2,17 @@
name: Bug report
about: Create a report to help us improve
title: ''
labels: "bug \U0001F41E"
labels: ''
assignees: ''
---
**Before feedback**
Before you feedback, please search for the issues to see if there are similar problems that can solve your problem.
**Please delete the above and the contents of this line, then fill in the feedback form in the following format, Thanks.**
<!-- Windows and Linux versions hide the application menu by default. Please use the keyboard shortcut "Ctrl+Shift+I" to open "Developer Tools" -->
**Describe the bug**
A clear and concise description of what the bug is.
@@ -23,12 +29,11 @@ A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. macOS, Windows, Linux]
- Version [e.g. 10.14.2, Win 10]
**App (please complete the following information):**
- Version [e.g. 1.1.0]
**Environment (please complete the following information):**
- OS & Version: [e.g. macOS, Windows, Linux]
- Version: [e.g. macOS 10.14.2, Windows 10, Ubuntu 18.04]
- Motrix Version: [e.g. v1.1.3, v1.1.0]
- Installation package type: [e.g. dmg, AppImage]
**Additional context**
Add any other context about the problem here.
+43
View File
@@ -0,0 +1,43 @@
---
name: 错误反馈
about: 创建一个错误报告帮助改进「请按照模板提交,提供详细的信息,方便我们复现之后处理」
title: ''
labels: ''
assignees: ''
---
<!--
反馈之前请搜索一下已有 issues 和 帮助文档,看是否有类似问题可以解决你的问题
https://github.com/agalwood/Motrix/issues
http://motrix.app/support
按以下格式填写反馈信息,谢谢
-->
**错误描述**
清楚简洁地描述错误,方便我们复现之后处理。
**如何重现**
重现步骤,如:
1. 点击新建任务按钮
2. 黏贴链接(如链接不涉及到隐私和版权问题,请顺便提供)
3. 点击提交
4. 发现报错
**预期的行为**
清楚简洁地描述你期望发生的事情。
**截图**
请添加屏幕截图以帮助解释你的问题:
打开应用菜单中的「帮助」——「开发者工具」—— 切换到 console,然后**完整**截图。
<!-- Windows 和 Linux 版本默认隐藏了应用菜单,请使用键盘快捷键 Ctrl+Shift+I 打开「开发者工具」 -->
**运行环境**
- 操作系统类型: [如 macOS, Windows, Linux]
- 具体版本: [如 macOS 10.14.2, Windows 10, Ubuntu 18.04]
- Motrix 版本: [如 v1.1.3, v1.1.0]
- 安装包类型:[如 dmg, AppImage]
**更多信息**
补充有关该问题的其他信息。
@@ -0,0 +1,28 @@
---
name: 新功能请求
about: 你期望 Motrix 未来添加的新功能
title: ''
labels: enhancement ✨
assignees: ''
---
<!--
反馈之前请搜索一下已有 issues 和 帮助文档,看是否已经有人提交了类似的新功能请求
https://github.com/agalwood/Motrix/issues
http://motrix.app/support
按以下格式填写反馈信息,谢谢
-->
**请描述一下你的新功能请求是否与已知问题有关?**
简明扼要地描述了问题所在。
**描述你想要的解决方案**
简明扼要地描述你想要的解决方案。
**描述你考虑过的替代方案**
简明扼要地描述你考虑过的任何替代解决方案或功能。
**更多信息**
补充有关该新功能的其他信息。
+16
View File
@@ -0,0 +1,16 @@
<!-- You can erase any parts of this template not applicable to your Pull Request. -->
## Description
<!-- Write a brief description of the changes introduced by this PR -->
## Related Issues
<!--
Link to the issue that is fixed by this PR (if there is one)
e.g. Fixes #1234, Addresses #1234, Related to #1234, etc.
-->
### Checklist:
* [ ] Have you checked to ensure there aren't other open [Pull Requests](../../../pulls) for the same update/change?
* [ ] Have you linted your code locally prior to submission?
* [ ] Have you successfully ran app with your changes locally?
+38
View File
@@ -0,0 +1,38 @@
# Configuration for Lock Threads - https://github.com/dessant/lock-threads
# Number of days of inactivity before a closed issue or pull request is locked
daysUntilLock: 60
# Skip issues and pull requests created before a given timestamp. Timestamp must
# follow ISO 8601 (`YYYY-MM-DD`). Set to `false` to disable
skipCreatedBefore: false
# Issues and pull requests with these labels will be ignored. Set to `[]` to disable
exemptLabels: []
# Label to add before locking, such as `outdated`. Set to `false` to disable
lockLabel: false
# Comment to post before locking. Set to `false` to disable
lockComment: >
This thread has been automatically locked since there has not been
any recent activity after it was closed. Please open a new issue for
related bugs.
# Assign `resolved` as the reason for locking. Set to `false` to disable
setLockReason: true
# Limit to only `issues` or `pulls`
# only: issues
# Optionally, specify configuration settings just for `issues` or `pulls`
# issues:
# exemptLabels:
# - help-wanted
# lockLabel: outdated
# pulls:
# daysUntilLock: 30
# Repository to extend settings from
# _extends: repo
+60
View File
@@ -0,0 +1,60 @@
name: Build/release
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
release:
runs-on: ${{ matrix.os }}
# Platforms to build on/for
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
steps:
- name: Check out Git repository
uses: actions/checkout@v2
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v2
with:
node-version: 12
- name: Install Snapcraft
uses: samuelmeuli/action-snapcraft@v1
# Only install Snapcraft on Ubuntu
if: startsWith(matrix.os, 'ubuntu')
with:
# Log in to Snap Store
snapcraft_token: ${{ secrets.snapcraft_token }}
- name: Prepare for app notarization (macOS)
if: startsWith(matrix.os, 'macos')
# Import Apple API key for app notarization on macOS
run: |
mkdir -p ~/private_keys/
echo '${{ secrets.api_key }}' > ~/private_keys/AuthKey_${{ secrets.api_key_id }}.p8
- name: Build/release Electron app
uses: samuelmeuli/action-electron-builder@v1
with:
build_script_name: 'build:github'
# GitHub token, automatically provided to the action
# (No need to define this secret in the repo settings)
github_token: ${{ secrets.github_token }}
# macOS code signing certificate
mac_certs: ${{ secrets.mac_certs }}
mac_certs_password: ${{ secrets.mac_certs_password }}
# If the commit is tagged with a version (e.g. "v1.0.0"),
# release the app after building
release: ${{ secrets.force_release == 'true' || startsWith(github.ref, 'refs/tags/v') }}
env:
# macOS notarization API key
API_KEY_ID: ${{ secrets.api_key_id }}
API_KEY_ISSUER_ID: ${{ secrets.api_key_issuer_id }}
+1
View File
@@ -9,3 +9,4 @@ npm-debug.log.*
thumbs.db
!.gitkeep
release/*
.idea/
+17 -5
View File
@@ -1,32 +1,44 @@
osx_image: xcode10.1
sudo: required
dist: trusty
language: c
matrix:
jobs:
include:
- os: osx
osx_image: xcode11.3
- os: linux
env: CC=clang CXX=clang++ npm_config_clang=1
compiler: clang
cache:
directories:
- node_modules
- "$HOME/.electron"
- "$HOME/.cache"
- $HOME/.cache/electron
- $HOME/.cache/electron-builder
addons:
apt:
packages:
- libgnome-keyring-dev
- icnsutils
- rpm
before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install --no-install-recommends -y icnsutils graphicsmagick xz-utils; fi
install:
- nvm install 10
- nvm install 12.14.1
- source ~/.bashrc
- npm install -g xvfb-maybe
- npm install
script:
- npm run release
before_cache:
- rm -rf $HOME/.cache/electron-builder/wine
branches:
only:
- master
+76
View File
@@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at agalwood.net@gmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
+41
View File
@@ -0,0 +1,41 @@
# Motrix 贡献指南
开始贡献之前,确保你已经理解了 [GitHub 的协作流程](https://guides.github.com/introduction/flow/)。
## 🌍 翻译指南
首先你要确定一个语言的英文简写作为 **locale**,如 en-US,这个 locale 值请严格参考 [Electron 的 Locales 文档](https://www.electronjs.org/docs/api/app#appgetlocale)
Motrix 的国际化分两部分:
- Element UI
- 菜单和主界面
### Element UI
Element UI 的国际化由 [Element 社区](http://element.eleme.io/#/en-US/component/i18n)提供,找到 **locale** 对应的语言包文件「两者 locale 命名可能不一致」,在 `src/shared/locales/all.js` 中引入,如
```javascript
import eleLocaleEn from 'element-ui/lib/locale/lang/en'
import eleLocaleZhCN from 'element-ui/lib/locale/lang/zh-CN'
```
### 菜单和主界面
Motrix 使用 i18next 作为翻译支持库,所以你可能需要简单了解一下它的[使用方法](https://www.i18next.com/overview/getting-started)。
配置文件按照语言 (**locale**) 划分目录:`src/shared/locales`,如:`src/shared/locales/en-US``src/shared/locales/zh-CN`
目录里面有按业务模块划分的语言文件
菜单模块经过重构之后,国际化已经打散到了以下文件里了,不再需要再复制 `src/main/menus` 里的配置。
- about.js
- app.js
- edit.js
- help.js
- index.js
- menu.js
- preferences.js
- subnav.js
- task.js
- window.js
+41
View File
@@ -0,0 +1,41 @@
# Motrix Contributing Guide
Before you start contributing, make sure you already understand [GitHub flow](https://guides.github.com/introduction/flow/).
## 🌍 Translation Guide
First you need to determine the English abbreviation of a language as **locale**, such as en-US, this locale value should strictly refer to the [electron's documentation](https://www.electronjs.org/docs/api/app#appgetlocale).
The internationalization of Motrix is divided into two parts:
- Element UI
- Menu & Main Interface
### Element UI
The internationalization of Element UI is provided by the [Element community](http://element.eleme.io/#/en-US/component/i18n), then find the language pack file corresponding to **locale** (both locale naming may be inconsistent), which is import in `src/shared/locales/all.js`, such as
```javascript
import eleLocaleEn from 'element-ui/lib/locale/lang/en'
import eleLocaleZhCN from 'element-ui/lib/locale/lang/zh-CN'
```
### Menu & Main Interface
Motrix uses the [i18next](https://www.i18next.com/overview/getting-started) library for internationalization, so you need a quick look at how to use it.
The configuration files are divided by **locale**: `src/shared/locales`, such as `src/shared/locales/en-US` and `src/shared/locales/zh-CN`.
There are language files in the directory according to the business module.
After the menu module is refactored, the internationalization of the menu has been dispersed into the following files, and there is no need to copy the configuration in `src/main/menus`.
- about.js
- app.js
- edit.js
- help.js
- index.js
- menu.js
- preferences.js
- subnav.js
- task.js
- window.js
+3 -1
View File
@@ -1,4 +1,6 @@
Copyright 2018 Dr_rOot
The MIT License
Copyright 2018-present Dr_rOot
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+133 -20
View File
@@ -1,82 +1,195 @@
# Motrix
<a href="https://motrix.app">
<img src="https://cdn.nlark.com/yuque/0/2018/png/129147/1543735425232-a5d2c99f-d788-43e4-9781-558ff6d21027.png" width="256" alt="App Icon" />
<img src="./static/512x512.png" width="256" alt="App Icon" />
</a>
## 一款全能的下载工具
[![GitHub release](https://img.shields.io/github/v/release/agalwood/Motrix.svg)](https://github.com/agalwood/Motrix/releases) ![Build/release](https://github.com/agalwood/Motrix/workflows/Build/release/badge.svg) ![Total Downloads](https://img.shields.io/github/downloads/agalwood/Motrix/total.svg) ![Support Platforms](https://camo.githubusercontent.com/a50c47295f350646d08f2e1ccd797ceca3840e52/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f706c6174666f726d2d6d61634f5325323025374325323057696e646f77732532302537432532304c696e75782d6c69676874677265792e737667)
[English](./README.md) | 简体中文
## 一款全能的下载工具
[![Build Status](https://travis-ci.org/agalwood/Motrix.svg?branch=master)](https://travis-ci.org/agalwood/Motrix) [![Build status](https://ci.appveyor.com/api/projects/status/l11d5h05xwwcvoux/branch/master?svg=true)](https://ci.appveyor.com/project/agalwood/motrix/branch/master) ![Total Downloads](https://img.shields.io/github/downloads/agalwood/Motrix/total.svg) ![Support Platforms](https://camo.githubusercontent.com/a50c47295f350646d08f2e1ccd797ceca3840e52/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f706c6174666f726d2d6d61634f5325323025374325323057696e646f77732532302537432532304c696e75782d6c69676874677265792e737667)
我是个兴趣使然的桌面应用开发者🤓,利用搬砖之余开发了 Motrix。
Motirx 是一款全能的下载工具,支持下载 HTTP、FTP、BT、磁力链、百度网盘等资源。它的界面简洁易用,希望大家喜欢 👻。
Motrix 是一款全能的下载工具,支持下载 HTTP、FTP、BT、磁力链等资源。它的界面简洁易用,希望大家喜欢 👻。
✈️ 去 [官网](https://motrix.app) 逛逛
✈️ 去 [官网](https://motrix.app/zh-CN) 逛逛 | 📖 查看 [帮助手册](http://motrix.app/support/issues)
## 💽 安装稳定版
[GitHub](https://github.com/agalwood/Motrix/releases) 和 [官网](https://motrix.app) 提供了已经编译好的稳定版安装包,当然你也可以自己克隆代码编译打包。
> 七牛CDN流量🔥烧不起,高峰时一天烧了110G的流量💸💸💸
[GitHub](https://github.com/agalwood/Motrix/releases) 和 [官网](https://motrix.app/zh-CN) 提供了已经编译好的稳定版安装包,当然你也可以自己克隆代码编译打包。
### Windows
建议使用安装包(Motrix-Setup-x.y.z.exe)安装 Motrix 以确保完整的体验,例如关联 torrent 文件,捕获磁力链等。
如果你更喜欢便携版,你可以使用 [scoop](https://github.com/lukesampson/scoop)(需要 Windows 7+,天朝用户可能需要设置 Git 代理)安装最新便携版本的 Motrix。
```bash
scoop bucket add extras
scoop install motrix
```
### macOS
macOS 用户可以使用 `brew cask` 安装 Motrix,感谢 [Mitscherlich](https://github.com/Mitscherlich) 的 [PR](https://github.com/Homebrew/homebrew-cask/pull/59494)。
```bash
brew update && brew install --cask motrix
```
### Linux
你可以下载 `AppImage` (适用于所有 Linux 发行版)或 `snap` 来安装 Motrix,更多 Linux 安装包格式请查看 [GitHub/release](https://github.com/agalwood/Motrix/releases) 。
如果你想自己通过编译源码来安装,请阅读 **编译打包** 部分。
#### AppImage
最新版的 Motrix AppImage 需要自己手动进执行桌面集成。请查看 [AppImageLauncher](https://github.com/TheAssassin/AppImageLauncher) 的文档进行操作。
> 桌面集成
> electron-builder v21 之后,桌面集成不再是 AppImage 文件的一部分。
> 推荐使用 [AppImageLauncher](https://github.com/TheAssassin/AppImageLauncher) 集成 AppImage。
Deepin 20 Beta 用户安装 Motrix 失败的问题,请按照以下方法处理:
打开`终端`,黏贴运行如下命令之后再次安装 Motrix。
```bash
sudo apt --fix-broken install
```
#### Snap
Motrix 已经上架 [Snapcraft](https://snapcraft.io/motrix) Ubuntu 用户推荐从 Snap 商店下载。
v1.5.10 提示
系统托盘可能无法正常显示指示器,导致退出应用程序不方便。
请取消勾选 偏好设置——基本设置——隐藏应用程序菜单(仅限Windows和Linux),点击保存并应用。然后点击 "文件 "菜单中的 "退出",退出应用程序。
请更新到 v1.5.12 及以上版本,可以使用键盘组合快捷键 <kbd>Ctrl</kbd> + <kbd>q</kbd> 快速退出应用。
#### AUR
对于 Arch Linux 用户,可以使用 [aur](https://aur.archlinux.org/packages/motrix/) 安装 Motrix,感谢维护者 [weearc](https://github.com/weearc)。
运行以下命令进行安装:
```bash
yay motrix
```
Motrix 在 Linux 中首次启动可能需要使用 `sudo` 运行,因为可能没有创建下载会话文件的权限 (`/var/cache/aria2.session`)。
## ✨ 特性
- 🕹 简洁明了的图形操作界面
- 🧲 支持BT和磁力链任务
- 🤫 支持下载百度云盘资源
- 🦄 支持BT和磁力链任务
- ☑️ 支持选择性下载BT部分文件
- 📡 每天自动更新 Tracker 服务器列表
- 🔌 UPnP & NAT-PMP 端口映射
- 🎛 最高支持 10 个任务同时下载
- 🚀 单任务最高支持 64 线程下载
- 🚥 设置上传/下载限速
- 🕶 模拟用户代理UA
- 🔔 下载完成后通知
- 💻 支持触控栏快捷 (Mac 专享)
- 💻 支持触控栏快捷 (Mac 专享)
- 🤖 常驻系统托盘,操作更加便捷
- 📟 系统托盘速度仪表显示实时速度 (Mac 专享)
- 🌑 深色模式
- 🗑 移除任务时可同时删除相关文件
- 🌍 国际化(可选择简体中文或英文界面)
- 🎏 ...
- 🌍 国际化[查看已可选的语言](#-国际化)
- 🛠 更多特性开发中
## 🖥 应用界面
![motrix-screenshot-task-cn.png](https://cdn.nlark.com/yuque/0/2019/png/129147/1548251088177-21762a41-3975-4417-bf54-6f64aeb0f20d.png)
![motrix-screenshot-task-cn.png](https://cdn.nlark.com/yuque/0/2020/png/129147/1589782239990-fecb9065-19ac-4c35-938b-0be45621ca3a.png)
## ⌨️ 本地开发
### 克隆代码
```bash
git clone git@github.com:agalwood/Motrix.git
```
### 安装依赖
```bash
cd Motrix
npm install
yarn
```
天朝大陆用户建议使用淘宝的npm源
天朝大陆用户建议使用淘宝的 npm 源
```bash
yarn config set registry 'https://registry.npm.taobao.org'
npm config set registry 'https://registry.npm.taobao.org'
export ELECTRON_MIRROR='https://npm.taobao.org/mirrors/electron/'
export SASS_BINARY_SITE='https://npm.taobao.org/mirrors/node-sass'
```
如果喜欢 [Yarn](https://yarnpkg.com/),也可以使用 `yarn` 安装依赖
> Error: Electron failed to install correctly, please delete node_modules/electron and try installing again
`Electron` 下载安装失败的问题,解决方式请参考 https://github.com/electron/electron/issues/8466#issuecomment-571425574
### 开发模式
```bash
npm run dev
yarn run dev
```
### 编译打包
```bash
npm run build
yarn run build
```
完成之后可以在项目的 `release` 目录看到编译打包好的应用文件
## 🛠 技术栈
- [Electron](https://electronjs.org/)
- [Vue](https://vuejs.org/) + [VueX](https://vuex.vuejs.org/) + [Element](https://element.eleme.io)
- [Aria2](https://aria2.github.io/) (注:macOS 和 Linux 版本使用的是 64 位的 aria2cWindows 版使用的 32 位的)
## ☑️ TODO
开发计划请移步 [Trello](https://trello.com/b/qNUzA0bv/motrix) 查看
## 🤝 参与共建 [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
## 🤝 参与共建 [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat)](http://makeapullrequest.com)
如果你有兴趣参与共同开发,欢迎 FORK 和 PR。
## 🌍 国际化
欢迎大家将 Motrix 翻译成更多的语言版本 🧐,开工之前请先阅读一下 [翻译指南](./CONTRIBUTING-CN.md#-翻译指南)。
| Key | Name | Status |
|-------|:--------------------|:-------------|
| ar | Arabic | ✔️ [@hadialqattan](https://github.com/hadialqattan), [@AhmedElTabarani](https://github.com/AhmedElTabarani) |
| bg | Българският език | ✔️ [@null-none](https://github.com/null-none) |
| ca | Català | ✔️ [@marcizhu](https://github.com/marcizhu) |
| de | Deutsch | ✔️ [@Schloemicher](https://github.com/Schloemicher) |
| el | Ελληνικά | ✔️ [@Likecinema](https://github.com/Likecinema) |
| en-US | English | ✔️ |
| es | Español | ✔️ [@Chofito](https://github.com/Chofito)|
| fa | فارسی | ✔️ [@Nima-Ra](https://github.com/Nima-Ra) |
| fr | Français | ✔️ [@gpatarin](https://github.com/gpatarin) |
| hu | Hungarian | ✔️ [@zalnaRs](https://github.com/zalnaRs) |
| id | Indonesia | ✔️ [@aarestu](https://github.com/aarestu) |
| it | Italiano | ✔️ [@blackcat-917](https://github.com/blackcat-917) |
| ja | 日本語 | ✔️ [@hbkrkzk](https://github.com/hbkrkzk) |
| ko | 한국어 | ✔️ [@KOZ39](https://github.com/KOZ39) |
| pl | Polski | ✔️ [@KanarekLife](https://github.com/KanarekLife) |
| pt-BR | Portuguese (Brazil) | ✔️ [@andrenoberto](https://github.com/andrenoberto) |
| ro | Română | ✔️ [@alyn3d](https://github.com/alyn3d) |
| ru | Русский | ✔️ [@bladeaweb](https://github.com/bladeaweb) |
| tr | Türkçe | ✔️ [@abdullah](https://github.com/abdullah) |
| uk | Українська | ✔️ [@bladeaweb](https://github.com/bladeaweb) |
| vi | Tiếng Việt | ✔️ [@duythanhvn](https://github.com/duythanhvn) |
| zh-CN | 简体中文 | ✔️ |
| zh-TW | 繁體中文 | ✔️ [@Yukaii](https://github.com/Yukaii) |
## 📜 开源许可
基于 [MIT license](https://opensource.org/licenses/MIT) 许可进行开源。
+134 -20
View File
@@ -1,74 +1,188 @@
# Motrix
<a href="https://motrix.app">
<img src="https://cdn.nlark.com/yuque/0/2018/png/129147/1543735425232-a5d2c99f-d788-43e4-9781-558ff6d21027.png" width="256" alt="App Icon" />
<img src="./static/512x512.png" width="256" alt="App Icon" />
</a>
## A full-featured download manager.
[![Build Status](https://travis-ci.org/agalwood/Motrix.svg?branch=master)](https://travis-ci.org/agalwood/Motrix) [![Build status](https://ci.appveyor.com/api/projects/status/l11d5h05xwwcvoux/branch/master?svg=true)](https://ci.appveyor.com/project/agalwood/motrix/branch/master) ![Total Downloads](https://img.shields.io/github/downloads/agalwood/Motrix/total.svg) ![Support Platforms](https://camo.githubusercontent.com/a50c47295f350646d08f2e1ccd797ceca3840e52/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f706c6174666f726d2d6d61634f5325323025374325323057696e646f77732532302537432532304c696e75782d6c69676874677265792e737667)
## A full-featured download manager
[![GitHub release](https://img.shields.io/github/v/release/agalwood/Motrix.svg)](https://github.com/agalwood/Motrix/releases) ![Build/release](https://github.com/agalwood/Motrix/workflows/Build/release/badge.svg) ![Total Downloads](https://img.shields.io/github/downloads/agalwood/Motrix/total.svg) ![Support Platforms](https://camo.githubusercontent.com/a50c47295f350646d08f2e1ccd797ceca3840e52/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f706c6174666f726d2d6d61634f5325323025374325323057696e646f77732532302537432532304c696e75782d6c69676874677265792e737667)
English | [简体中文](./README-CN.md)
Motrix is a full-featured download manager that support downloading HTTP, FTP, BitTorrent, Magnet, Baidu Net Disk etc.
Motrix is a full-featured download manager that supports downloading HTTP, FTP, BitTorrent, Magnet, etc.
It has a clean and simple interface and is easy to use. I hope you will like it 👻.
Motrix has a clean and easy to use interface. I hope you will like it 👻.
✈️ [Official Website](https://motrix.app)
✈️ [Official Website](https://motrix.app) | 📖 [Manual](https://github.com/agalwood/Motrix/wiki)
## 💽 Installation
Download from [GitHub Releases](https://github.com/agalwood/Motrix/releases) and install it.
### Windows
It is recommended to install Motrix using the installation package (Motrix-Setup-x.y.z.exe) to ensure a complete experience, such as associating torrent files, capturing magnet links, etc.
If you prefer the portable version, you can use [scoop](https://github.com/lukesampson/scoop) (need Windows 7+) to install Motrix.
```bash
scoop bucket add extras
scoop install motrix
```
### macOS
The macOS users can install Motrix using `brew cask`, thanks to [PR](https://github.com/Homebrew/homebrew-cask/pull/59494) of [Mitscherlich](https://github.com/Mitscherlich).
```bash
brew update && brew install --cask motrix
```
### Linux
You can download the `AppImage` (for all Linux distributions) or `snap` to install Motrix, see [GitHub/release](https://github.com/agalwood/Motrix/releases) for more Linux installation package formats.
If you want to build from source code, please read the **Build** section.
#### AppImage
The latest version of Motrix AppImage requires you to manually perform desktop integration. Please check the documentation of [AppImageLauncher](https://github.com/TheAssassin/AppImageLauncher) .
> Desktop Integration
> Since electron-builder 21 desktop integration is not a part of produced AppImage file.
> [AppImageLauncher](https://github.com/TheAssassin/AppImageLauncher) is the recommended way to integrate AppImages.
Deepin 20 Beta users failed to install Motrix, please follow the steps below:
Open the `Terminal`, paste and run the following command to install Motrix again.
```bash
sudo apt --fix-broken install
```
#### Snap
Motrix has been listed on [Snapcraft](https://snapcraft.io/motrix) , Ubuntu users recommend downloading from the Snap Store.
Tips for v1.5.10
The tray may not display the indicator normally, which makes it inconvenient to exit the application.
Please unchecked Preferences--Basic Settings--Hide App Menu (Windows & Linux Only), click Save & Apply. Then click "Exit" in the File menu to exit the application.
Please update to v1.5.12 and above, you can use the keyboard shortcut <kbd>Ctrl</kbd> + <kbd>q</kbd> to quickly exit the application.
#### AUR
For Arch Linux users, Motrix is available in [aur](https://aur.archlinux.org/packages/motrix/), thanks to the maintainer [weearc](https://github.com/weearc).
Run the following command to install:
```bash
yay motrix
```
Motrix may need to run with `sudo` for the first time in Linux because there is no permission to create the download session file (`/var/cache/aria2.session`).
## ✨ Features
- 🕹 Simple and clear user interface
- 🧲 Support BitTorrent & Magnet
- 🤫 Support downloading Baidu Net Disk
- 🎛 Up to 10 tasks concurrently download
- 🚀 Single task maximum support 64 thread download
- 🦄 Supports BitTorrent & Magnet
- ☑️ BitTorrent selective download
- 📡 Update tracker list every day automatically
- 🔌 UPnP & NAT-PMP Port Mapping
- 🎛 Up to 10 concurrent download tasks
- 🚀 Supports 64 threads in a single task
- 🚥 Supports speed limit
- 🕶 Mock User-Agent
- 🔔 Download completed Notification
- 💻 Ready for Touch Bar (Mac only)
- 🤖 Resident system tray for quick operation
- 📟 Tray speed meter displays real-time speed (Mac only)
- 🌑 Dark mode
- 🗑 Delete related files when removing tasks (optional)
- 🌍 I18n, currently available Simplified Chinese & English.
- 🎏 ...
- 🌍 I18n, [View supported languages](#-internationalization).
- 🛠 More features in development
## 🖥 User Interface
![motrix-screenshot-task-en.png](https://cdn.nlark.com/yuque/0/2019/png/129147/1548251350313-73aa0d60-ee31-4405-bdb9-1793e3fd46ef.png)
![motrix-screenshot-task-en.png](https://cdn.nlark.com/yuque/0/2020/png/129147/1589782238501-e7b39166-da58-4152-ae34-65a061cafa48.png)
## ⌨️ Development
### Clone Code
```bash
git clone git@github.com:agalwood/Motrix.git
```
### Install Dependencies
```bash
cd Motrix
npm install
yarn
```
If you like [Yarn](https://yarnpkg.com/), you can also use `yarn` to install dependencies.
> Error: Electron failed to install correctly, please delete node_modules/electron and try installing again
`Electron` failed to install correctly, please refer to https://github.com/electron/electron/issues/8466#issuecomment-571425574
### Dev Mode
```bash
npm run dev
yarn run dev
```
### Build Release
```bash
npm run build
yarn run build
```
After build finish, you can see the compiled packaged application file in the `release` directory of the project.
After building, the application will be found in the project's `release` directory.
## 🛠 Technology Stack
- [Electron](https://electronjs.org/)
- [Vue](https://vuejs.org/) + [VueX](https://vuex.vuejs.org/) + [Element](https://element.eleme.io)
- [Aria2](https://aria2.github.io/) (Note: macOS and Linux versions use 64-bit aria2c, Windows version uses 32-bit)
## ☑️ TODO
Development Roadmap see: [Trello](https://trello.com/b/qNUzA0bv/motrix)
## 🤝 Contribute [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
If you are interested in participating in joint development, Fork and PR are welcome.
## 🤝 Contribute [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat)](http://makeapullrequest.com)
If you are interested in participating in joint development, PR and Forks are welcome!
## 🌍 Internationalization
Translations into versions for other languages are welcome 🧐! Please read the [translation guide](./CONTRIBUTING.md#-translation-guide) before starting translations.
| Key | Name | Status |
|-------|:--------------------|:-------------|
| ar | Arabic | ✔️ [@hadialqattan](https://github.com/hadialqattan), [@AhmedElTabarani](https://github.com/AhmedElTabarani) |
| bg | Българският език | ✔️ [@null-none](https://github.com/null-none) |
| ca | Català | ✔️ [@marcizhu](https://github.com/marcizhu) |
| de | Deutsch | ✔️ [@Schloemicher](https://github.com/Schloemicher) |
| el | Ελληνικά | ✔️ [@Likecinema](https://github.com/Likecinema) |
| en-US | English | ✔️ |
| es | Español | ✔️ [@Chofito](https://github.com/Chofito)|
| fa | فارسی | ✔️ [@Nima-Ra](https://github.com/Nima-Ra) |
| fr | Français | ✔️ [@gpatarin](https://github.com/gpatarin) |
| hu | Hungarian | ✔️ [@zalnaRs](https://github.com/zalnaRs) |
| id | Indonesia | ✔️ [@aarestu](https://github.com/aarestu) |
| it | Italiano | ✔️ [@blackcat-917](https://github.com/blackcat-917) |
| ja | 日本語 | ✔️ [@hbkrkzk](https://github.com/hbkrkzk) |
| ko | 한국어 | ✔️ [@KOZ39](https://github.com/KOZ39) |
| pl | Polski | ✔️ [@KanarekLife](https://github.com/KanarekLife) |
| pt-BR | Portuguese (Brazil) | ✔️ [@andrenoberto](https://github.com/andrenoberto) |
| ro | Română | ✔️ [@alyn3d](https://github.com/alyn3d) |
| ru | Русский | ✔️ [@bladeaweb](https://github.com/bladeaweb) |
| tr | Türkçe | ✔️ [@abdullah](https://github.com/abdullah) |
| uk | Українська | ✔️ [@bladeaweb](https://github.com/bladeaweb) |
| vi | Tiếng Việt | ✔️ [@duythanhvn](https://github.com/duythanhvn) |
| zh-CN | 简体中文 | ✔️ |
| zh-TW | 繁體中文 | ✔️ [@Yukaii](https://github.com/Yukaii) |
## 📜 License
[MIT](https://opensource.org/licenses/MIT) Copyright (c) 2018-present Dr_rOot
+1 -1
View File
@@ -1,2 +1,2 @@
provider: generic
url: 'https://motrix.app/release/'
url: 'https://dl.motrix.app/release/'
+6 -9
View File
@@ -1,24 +1,17 @@
version: 1.0.{build}
branches:
only:
- master
image: Visual Studio 2017
platform:
- x64
cache:
- node_modules
- '%APPDATA%\npm-cache'
- '%USERPROFILE%\.electron'
- '%USERPROFILE%\AppData\Local\Yarn\cache'
init:
- git config --global core.autocrlf input
install:
- ps: Install-Product node 10 x64
- ps: Install-Product node 12.14.1 x64
- git reset --hard HEAD
- npm install
- node --version
@@ -27,3 +20,7 @@ build_script:
- npm run release
test: off
branches:
only:
- master
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 24 KiB

+94
View File
@@ -0,0 +1,94 @@
// Forked from https://github.com/samuelmeuli/mini-diary/blob/master/scripts/after-pack.js
/**
* Source: https://github.com/patrikx3/redis-ui/blob/master/src/build/after-pack.js
*
* Copyright (c) 2019 Patrik Laszlo / P3X / Corifeus and contributors.
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
// TODO: Remove script once https://github.com/electron/electron/issues/17972 is solved by
// `electron-builder`
const fs = require('fs')
const { spawn } = require('child_process')
const { chdir } = require('process')
const pkg = require('../package.json')
const binName = `${pkg.name}`.toLowerCase()
const exec = async function exec (cmd, args = []) {
const child = spawn(cmd, args, { shell: true })
redirectOutputFor(child)
await waitFor(child)
}
const redirectOutputFor = child => {
const printStdout = data => {
process.stdout.write(data.toString())
}
const printStderr = data => {
process.stderr.write(data.toString())
}
child.stdout.on('data', printStdout)
child.stderr.on('data', printStderr)
child.once('close', () => {
child.stdout.off('data', printStdout)
child.stderr.off('data', printStderr)
})
}
const waitFor = async function (child) {
return new Promise(resolve => {
child.once('close', () => resolve())
})
}
const linuxTargets = [
'AppImage',
'deb',
'rpm',
'snap'
]
module.exports = async function (context) {
console.warn('after build; disable sandbox')
const isLinux = context.targets.find(
target => linuxTargets.includes(target)
)
if (!isLinux) {
return
}
const originalDir = process.cwd()
const dirname = context.appOutDir
chdir(dirname)
await exec('mv', [binName, binName + '.bin'])
const wrapperScript = `#!/bin/bash
"\${BASH_SOURCE%/*}"/${binName}.bin "$@" --no-sandbox
`
fs.writeFileSync(binName, wrapperScript)
await exec('chmod', ['+x', binName])
chdir(originalDir)
}
+27
View File
@@ -0,0 +1,27 @@
require('dotenv').config()
const { notarize } = require('electron-notarize')
const pkg = require('../package.json')
exports.default = async function (context) {
const { electronPlatformName, appOutDir } = context
if (electronPlatformName !== 'darwin') {
return
}
const skipNotarize = process.env.SKIP_NOTARIZE
if (skipNotarize === 'yes') {
console.log('skipping notarize')
return
}
const appBundleId = pkg.build.appId
const appName = context.packager.appInfo.productFilename
return await notarize({
appBundleId,
appPath: `${appOutDir}/${appName}.app`,
ascProvider: process.env.TEAM_ID,
appleId: process.env.APPLE_ID,
appleIdPassword: process.env.APPLE_ID_PWD
})
}
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

+3
View File
@@ -0,0 +1,3 @@
# aria2
Source code: https://github.com/agalwood/aria2
Executable → Regular
+66 -99
View File
@@ -1,108 +1,75 @@
## '#'开头为注释内容, 选项都有相应的注释说明, 根据需要修改 ##
## 被注释的选项填写的是默认值, 建议在需要修改时再取消注释 ##
## 添加了@和默认启用的选项都是系统需要调用的,请不要随意改动否则可能无法正常运行
###############################
# Motrix macOS Aria2 config file
#
# @see https://aria2.github.io/manual/en/html/aria2c.html
#
###############################
## 文件保存相关 ##
# 文件的保存路径(可使用绝对路径或相对路径), 默认: 当前启动位置
# 此项 OS X 无法使用 $HOME 及 ~/ 设置路径 建议使用 /users/用户名/downloads
#@dir=$HOME/downloads
# 启用磁盘缓存, 0为禁用缓存, 需1.16以上版本, 默认:16M
#@disk-cache=32M
# 文件预分配方式, 能有效降低磁盘碎片, 默认:prealloc
# 预分配所需时间: none < falloc ? trunc < prealloc
# falloc和trunc则需要文件系统和内核支持
# NTFS建议使用falloc, EXT3/4建议trunc, MAC 下需要注释此项
# file-allocation=none
# 断点续传
#@continue=true
## 下载连接相关 ##
# 最大同时下载任务数, 运行时可修改, 默认:5
#@max-concurrent-downloads=10
# 同一服务器连接数, 添加时可指定, 默认:1
#@max-connection-per-server=15
# 最小文件分片大小, 添加时可指定, 取值范围1M -1024M, 默认:20M
# 假定size=10M, 文件为20MiB 则使用两个来源下载; 文件为15MiB 则使用一个来源下载
#@min-split-size=10M
# 单个任务最大线程数, 添加时可指定, 默认:5
#@split=15
# 整体下载速度限制, 运行时可修改, 默认:0
#@max-overall-download-limit=0
# 单个任务下载速度限制, 默认:0
#@max-download-limit=0
# 整体上传速度限制, 运行时可修改, 默认:0
#@max-overall-upload-limit=0
# 单个任务上传速度限制, 默认:0
#@max-upload-limit=0
# 禁用IPv6, 默认:false
disable-ipv6=false
#运行覆盖已存在文件
#@allow-overwrite=true
#自动重命名
#@auto-file-renaming=true
## 进度保存相关 ##
# 从会话文件中读取下载任务
#@input-file=/Users/Shared/aria2.session
# 在Aria2退出时保存`错误/未完成`的下载任务到会话文件
#@save-session=/Users/Shared/aria2.session
# 定时保存会话, 0为退出时才保存, 需1.16.1以上版本, 默认:0
save-session-interval=30
## RPC相关设置 ##
# 启用RPC, 默认:false
################ RPC ################
# Enable JSON-RPC/XML-RPC server.
enable-rpc=true
# 允许所有来源, 默认:false
# Add Access-Control-Allow-Origin header field with value * to the RPC response.
rpc-allow-origin-all=true
# 允许非外部访问, 默认:false
# Listen incoming JSON-RPC/XML-RPC requests on all network interfaces.
rpc-listen-all=true
# 事件轮询方式, 取值:[epoll, kqueue, port, poll, select], 不同系统默认值不同
#event-poll=select
# RPC监听端口, 端口被占用时可以修改, 默认:6800
# 使用本客户端请勿修改此项
# rpc-listen-port=6800
# 设置的RPC授权令牌, v1.18.4新增功能, 取代 --rpc-user 和 --rpc-passwd 选项
#rpc-secret=token
## BT/PT下载相关 ##
# 当下载的是一个种子(以.torrent结尾)时, 自动开始BT任务, 默认:true
#follow-torrent=true
# BT监听端口, 当端口被屏蔽时使用, 默认:6881-6999
listen-port=51413
# 单个种子最大连接数, 默认:55
#bt-max-peers=55
# 打开DHT功能, PT需要禁用, 默认:true
# enable-dht=false
# 打开IPv6 DHT功能, PT需要禁用
#enable-dht6=false
# DHT网络监听端口, 默认:6881-6999
#dht-listen-port=6881-6999
# 本地节点查找, PT需要禁用, 默认:false
bt-enable-lpd=true
# 种子交换, PT需要禁用, 默认:true
enable-peer-exchange=true
# 每个种子限速, 对少种的PT很有用, 默认:50K
#bt-request-peer-speed-limit=50K
# 客户端伪装, PT需要
peer-id-prefix=-TR2770-
################ File system ################
# Save a control file(*.aria2) every SEC seconds.
auto-save-interval=10
# Enable disk cache.
disk-cache=32M
# Specify file allocation method.
file-allocation=falloc
# Save error/unfinished downloads to a file specified by --save-session option every SEC seconds.
save-session-interval=10
################ Task ################
# Exclude seed only downloads when counting concurrent active downloads
bt-detach-seed-only=true
# Verify the peer using certificates specified in --ca-certificate option.
check-certificate=false
# If aria2 receives "file not found" status from the remote HTTP/FTP servers NUM times
# without getting a single byte, then force the download to fail.
max-file-not-found=5
# Set number of tries.
max-tries=5
# aria2 does not split less than 2*SIZE byte range.
min-split-size=1M
# Set user agent for HTTP(S) downloads.
user-agent=Transmission/2.94
# 当种子的分享率达到这个数时, 自动停止做种, 0为一直做种, 默认:1.0
seed-ratio=1.0
# 强制保存会话, 即使任务已经完成, 默认:false
# 较新的版本开启后会在任务完成后依然保留.aria2文件
#force-save=false
# BT校验相关, 默认:true
#bt-hash-check-seed=true
# 继续之前的BT任务时, 无需再次校验, 默认:false
# Send Accept: deflate, gzip request header
http-accept-gzip=true
################ BT Task ################
# Enable Local Peer Discovery.
bt-enable-lpd=true
# Requires BitTorrent message payload encryption with arc4.
# bt-force-encryption=true
# If true is given, after hash check using --check-integrity option and file is complete, continue to seed file.
bt-hash-check-seed=true
# Specify the maximum number of peers per torrent.
bt-max-peers=255
# Try to download first and last pieces of each file first. This is useful for previewing files.
bt-prioritize-piece=head
# Removes the unselected files when download is completed in BitTorrent.
bt-remove-unselected-file=true
# Seed previously downloaded files without verifying piece hashes.
bt-seed-unverified=true
# 保存磁力链接元数据为种子文件(.torrent文件), 默认:false
bt-save-metadata=true
# bt-tracker数据来自https://github.com/ngosang/trackerslist/blob/master/trackers_best.txt
bt-tracker=udp://tracker.coppersurfer.tk:6969/announce,udp://tracker.opentrackr.org:1337/announce,udp://tracker.internetwarriors.net:1337/announce,udp://9.rarbg.to:2710/announce,udp://exodus.desync.com:6969/announce,udp://tracker2.itzmx.com:6961/announce,udp://tracker1.itzmx.com:8080/announce,udp://explodie.org:6969/announce,http://tracker.tfile.me:80/announce.php,http://tracker.tfile.me:80/announce,http://tracker.tfile.co:80/announce,http://peersteers.org:80/announce,udp://tracker.tiny-vps.com:6969/announce,udp://ipv4.tracker.harry.lu:80/announce,udp://denis.stalker.upeer.me:6969/announce,udp://tracker.torrent.eu.org:451/announce,udp://tracker.port443.xyz:6969/announce,udp://tracker.cyberia.is:6969/announce,udp://thetracker.org:80/announce,udp://retracker.lanta-net.ru:2710/announce
# Set host and port as an entry point to IPv4 DHT network.
dht-entry-point=dht.transmissionbt.com:6881
# Set host and port as an entry point to IPv6 DHT network.
dht-entry-point6=dht.transmissionbt.com:6881
# Enable IPv4 DHT functionality. It also enables UDP tracker support.
enable-dht=true
# Enable IPv6 DHT functionality.
enable-dht6=true
# Enable Peer Exchange extension.
enable-peer-exchange=true
# Specify the string used during the bitorrent extended handshake for the peer's client version.
peer-agent=Transmission/2.94
# Specify the prefix of peer ID.
peer-id-prefix=-TR2940-
Binary file not shown.
Executable → Regular
+66 -99
View File
@@ -1,108 +1,75 @@
## '#'开头为注释内容, 选项都有相应的注释说明, 根据需要修改 ##
## 被注释的选项填写的是默认值, 建议在需要修改时再取消注释 ##
## 添加了@和默认启用的选项都是系统需要调用的,请不要随意改动否则可能无法正常运行
###############################
# Motrix Linux Aria2 config file
#
# @see https://aria2.github.io/manual/en/html/aria2c.html
#
###############################
## 文件保存相关 ##
# 文件的保存路径(可使用绝对路径或相对路径), 默认: 当前启动位置
# 此项 OS X 无法使用 $HOME 及 ~/ 设置路径 建议使用 /users/用户名/downloads
#@dir=$HOME/downloads
# 启用磁盘缓存, 0为禁用缓存, 需1.16以上版本, 默认:16M
#@disk-cache=32M
# 文件预分配方式, 能有效降低磁盘碎片, 默认:prealloc
# 预分配所需时间: none < falloc ? trunc < prealloc
# falloc和trunc则需要文件系统和内核支持
# NTFS建议使用falloc, EXT3/4建议trunc, MAC 下需要注释此项
file-allocation=trunc
# 断点续传
#@continue=true
## 下载连接相关 ##
# 最大同时下载任务数, 运行时可修改, 默认:5
#@max-concurrent-downloads=10
# 同一服务器连接数, 添加时可指定, 默认:1
#@max-connection-per-server=15
# 最小文件分片大小, 添加时可指定, 取值范围1M -1024M, 默认:20M
# 假定size=10M, 文件为20MiB 则使用两个来源下载; 文件为15MiB 则使用一个来源下载
#@min-split-size=10M
# 单个任务最大线程数, 添加时可指定, 默认:5
#@split=15
# 整体下载速度限制, 运行时可修改, 默认:0
#@max-overall-download-limit=0
# 单个任务下载速度限制, 默认:0
#@max-download-limit=0
# 整体上传速度限制, 运行时可修改, 默认:0
#@max-overall-upload-limit=0
# 单个任务上传速度限制, 默认:0
#@max-upload-limit=0
# 禁用IPv6, 默认:false
disable-ipv6=false
#运行覆盖已存在文件
#@allow-overwrite=true
#自动重命名
#@auto-file-renaming=true
## 进度保存相关 ##
# 从会话文件中读取下载任务
#@input-file=/Users/Shared/aria2.session
# 在Aria2退出时保存`错误/未完成`的下载任务到会话文件
#@save-session=/Users/Shared/aria2.session
# 定时保存会话, 0为退出时才保存, 需1.16.1以上版本, 默认:0
save-session-interval=30
## RPC相关设置 ##
# 启用RPC, 默认:false
################ RPC ################
# Enable JSON-RPC/XML-RPC server.
enable-rpc=true
# 允许所有来源, 默认:false
# Add Access-Control-Allow-Origin header field with value * to the RPC response.
rpc-allow-origin-all=true
# 允许非外部访问, 默认:false
# Listen incoming JSON-RPC/XML-RPC requests on all network interfaces.
rpc-listen-all=true
# 事件轮询方式, 取值:[epoll, kqueue, port, poll, select], 不同系统默认值不同
#event-poll=select
# RPC监听端口, 端口被占用时可以修改, 默认:6800
# 使用本客户端请勿修改此项
# rpc-listen-port=6800
# 设置的RPC授权令牌, v1.18.4新增功能, 取代 --rpc-user 和 --rpc-passwd 选项
#rpc-secret=token
## BT/PT下载相关 ##
# 当下载的是一个种子(以.torrent结尾)时, 自动开始BT任务, 默认:true
#follow-torrent=true
# BT监听端口, 当端口被屏蔽时使用, 默认:6881-6999
listen-port=51413
# 单个种子最大连接数, 默认:55
#bt-max-peers=55
# 打开DHT功能, PT需要禁用, 默认:true
# enable-dht=false
# 打开IPv6 DHT功能, PT需要禁用
#enable-dht6=false
# DHT网络监听端口, 默认:6881-6999
#dht-listen-port=6881-6999
# 本地节点查找, PT需要禁用, 默认:false
bt-enable-lpd=true
# 种子交换, PT需要禁用, 默认:true
enable-peer-exchange=true
# 每个种子限速, 对少种的PT很有用, 默认:50K
#bt-request-peer-speed-limit=50K
# 客户端伪装, PT需要
peer-id-prefix=-TR2770-
################ File system ################
# Save a control file(*.aria2) every SEC seconds.
auto-save-interval=10
# Enable disk cache.
disk-cache=32M
# Specify file allocation method.
file-allocation=trunc
# Save error/unfinished downloads to a file specified by --save-session option every SEC seconds.
save-session-interval=10
################ Task ################
# Exclude seed only downloads when counting concurrent active downloads
bt-detach-seed-only=true
# Verify the peer using certificates specified in --ca-certificate option.
check-certificate=false
# If aria2 receives "file not found" status from the remote HTTP/FTP servers NUM times
# without getting a single byte, then force the download to fail.
max-file-not-found=5
# Set number of tries.
max-tries=5
# aria2 does not split less than 2*SIZE byte range.
min-split-size=1M
# Set user agent for HTTP(S) downloads.
user-agent=Transmission/2.94
# 当种子的分享率达到这个数时, 自动停止做种, 0为一直做种, 默认:1.0
seed-ratio=1.0
# 强制保存会话, 即使任务已经完成, 默认:false
# 较新的版本开启后会在任务完成后依然保留.aria2文件
#force-save=false
# BT校验相关, 默认:true
#bt-hash-check-seed=true
# 继续之前的BT任务时, 无需再次校验, 默认:false
# Send Accept: deflate, gzip request header
http-accept-gzip=true
################ BT Task ################
# Enable Local Peer Discovery.
bt-enable-lpd=true
# Requires BitTorrent message payload encryption with arc4.
# bt-force-encryption=true
# If true is given, after hash check using --check-integrity option and file is complete, continue to seed file.
bt-hash-check-seed=true
# Specify the maximum number of peers per torrent.
bt-max-peers=255
# Try to download first and last pieces of each file first. This is useful for previewing files.
bt-prioritize-piece=head
# Removes the unselected files when download is completed in BitTorrent.
bt-remove-unselected-file=true
# Seed previously downloaded files without verifying piece hashes.
bt-seed-unverified=true
# 保存磁力链接元数据为种子文件(.torrent文件), 默认:false
bt-save-metadata=true
# bt-tracker数据来自https://github.com/ngosang/trackerslist/blob/master/trackers_best.txt
bt-tracker=udp://tracker.coppersurfer.tk:6969/announce,udp://tracker.opentrackr.org:1337/announce,udp://tracker.internetwarriors.net:1337/announce,udp://9.rarbg.to:2710/announce,udp://exodus.desync.com:6969/announce,udp://tracker2.itzmx.com:6961/announce,udp://tracker1.itzmx.com:8080/announce,udp://explodie.org:6969/announce,http://tracker.tfile.me:80/announce.php,http://tracker.tfile.me:80/announce,http://tracker.tfile.co:80/announce,http://peersteers.org:80/announce,udp://tracker.tiny-vps.com:6969/announce,udp://ipv4.tracker.harry.lu:80/announce,udp://denis.stalker.upeer.me:6969/announce,udp://tracker.torrent.eu.org:451/announce,udp://tracker.port443.xyz:6969/announce,udp://tracker.cyberia.is:6969/announce,udp://thetracker.org:80/announce,udp://retracker.lanta-net.ru:2710/announce
# Set host and port as an entry point to IPv4 DHT network.
dht-entry-point=dht.transmissionbt.com:6881
# Set host and port as an entry point to IPv6 DHT network.
dht-entry-point6=dht.transmissionbt.com:6881
# Enable IPv4 DHT functionality. It also enables UDP tracker support.
enable-dht=true
# Enable IPv6 DHT functionality.
enable-dht6=true
# Enable Peer Exchange extension.
enable-peer-exchange=true
# Specify the string used during the bitorrent extended handshake for the peer's client version.
peer-agent=Transmission/2.94
# Specify the prefix of peer ID.
peer-id-prefix=-TR2940-
Binary file not shown.
Executable → Regular
+66 -99
View File
@@ -1,108 +1,75 @@
## '#'开头为注释内容, 选项都有相应的注释说明, 根据需要修改 ##
## 被注释的选项填写的是默认值, 建议在需要修改时再取消注释 ##
## 添加了@和默认启用的选项都是系统需要调用的,请不要随意改动否则可能无法正常运行
###############################
# Motrix Windows Aria2 config file
#
# @see https://aria2.github.io/manual/en/html/aria2c.html
#
###############################
## 文件保存相关 ##
# 文件的保存路径(可使用绝对路径或相对路径), 默认: 当前启动位置
# 此项 OS X 无法使用 $HOME 及 ~/ 设置路径 建议使用 /users/用户名/downloads
#@dir=$HOME/downloads
# 启用磁盘缓存, 0为禁用缓存, 需1.16以上版本, 默认:16M
#@disk-cache=32M
# 文件预分配方式, 能有效降低磁盘碎片, 默认:prealloc
# 预分配所需时间: none < falloc ? trunc < prealloc
# falloc和trunc则需要文件系统和内核支持
# NTFS建议使用falloc, EXT3/4建议trunc, MAC 下需要注释此项
file-allocation=falloc
# 断点续传
#@continue=true
## 下载连接相关 ##
# 最大同时下载任务数, 运行时可修改, 默认:5
#@max-concurrent-downloads=10
# 同一服务器连接数, 添加时可指定, 默认:1
#@max-connection-per-server=15
# 最小文件分片大小, 添加时可指定, 取值范围1M -1024M, 默认:20M
# 假定size=10M, 文件为20MiB 则使用两个来源下载; 文件为15MiB 则使用一个来源下载
#@min-split-size=10M
# 单个任务最大线程数, 添加时可指定, 默认:5
#@split=15
# 整体下载速度限制, 运行时可修改, 默认:0
#@max-overall-download-limit=0
# 单个任务下载速度限制, 默认:0
#@max-download-limit=0
# 整体上传速度限制, 运行时可修改, 默认:0
#@max-overall-upload-limit=0
# 单个任务上传速度限制, 默认:0
#@max-upload-limit=0
# 禁用IPv6, 默认:false
disable-ipv6=false
#运行覆盖已存在文件
#@allow-overwrite=true
#自动重命名
#@auto-file-renaming=true
## 进度保存相关 ##
# 从会话文件中读取下载任务
#@input-file=/Users/Shared/aria2.session
# 在Aria2退出时保存`错误/未完成`的下载任务到会话文件
#@save-session=/Users/Shared/aria2.session
# 定时保存会话, 0为退出时才保存, 需1.16.1以上版本, 默认:0
save-session-interval=30
## RPC相关设置 ##
# 启用RPC, 默认:false
################ RPC ################
# Enable JSON-RPC/XML-RPC server.
enable-rpc=true
# 允许所有来源, 默认:false
# Add Access-Control-Allow-Origin header field with value * to the RPC response.
rpc-allow-origin-all=true
# 允许非外部访问, 默认:false
# Listen incoming JSON-RPC/XML-RPC requests on all network interfaces.
rpc-listen-all=true
# 事件轮询方式, 取值:[epoll, kqueue, port, poll, select], 不同系统默认值不同
#event-poll=select
# RPC监听端口, 端口被占用时可以修改, 默认:6800
# 使用本客户端请勿修改此项
# rpc-listen-port=6800
# 设置的RPC授权令牌, v1.18.4新增功能, 取代 --rpc-user 和 --rpc-passwd 选项
#rpc-secret=token
## BT/PT下载相关 ##
# 当下载的是一个种子(以.torrent结尾)时, 自动开始BT任务, 默认:true
#follow-torrent=true
# BT监听端口, 当端口被屏蔽时使用, 默认:6881-6999
listen-port=51413
# 单个种子最大连接数, 默认:55
#bt-max-peers=55
# 打开DHT功能, PT需要禁用, 默认:true
# enable-dht=false
# 打开IPv6 DHT功能, PT需要禁用
#enable-dht6=false
# DHT网络监听端口, 默认:6881-6999
#dht-listen-port=6881-6999
# 本地节点查找, PT需要禁用, 默认:false
bt-enable-lpd=true
# 种子交换, PT需要禁用, 默认:true
enable-peer-exchange=true
# 每个种子限速, 对少种的PT很有用, 默认:50K
#bt-request-peer-speed-limit=50K
# 客户端伪装, PT需要
peer-id-prefix=-TR2770-
################ File system ################
# Save a control file(*.aria2) every SEC seconds.
auto-save-interval=10
# Enable disk cache.
disk-cache=32M
# Specify file allocation method.
file-allocation=falloc
# Save error/unfinished downloads to a file specified by --save-session option every SEC seconds.
save-session-interval=10
################ Task ################
# Exclude seed only downloads when counting concurrent active downloads
bt-detach-seed-only=true
# Verify the peer using certificates specified in --ca-certificate option.
check-certificate=false
# If aria2 receives "file not found" status from the remote HTTP/FTP servers NUM times
# without getting a single byte, then force the download to fail.
max-file-not-found=5
# Set number of tries.
max-tries=5
# aria2 does not split less than 2*SIZE byte range.
min-split-size=1M
# Set user agent for HTTP(S) downloads.
user-agent=Transmission/2.94
# 当种子的分享率达到这个数时, 自动停止做种, 0为一直做种, 默认:1.0
seed-ratio=1.0
# 强制保存会话, 即使任务已经完成, 默认:false
# 较新的版本开启后会在任务完成后依然保留.aria2文件
#force-save=false
# BT校验相关, 默认:true
#bt-hash-check-seed=true
# 继续之前的BT任务时, 无需再次校验, 默认:false
# Send Accept: deflate, gzip request header
http-accept-gzip=true
################ BT Task ################
# Enable Local Peer Discovery.
bt-enable-lpd=true
# Requires BitTorrent message payload encryption with arc4.
# bt-force-encryption=true
# If true is given, after hash check using --check-integrity option and file is complete, continue to seed file.
bt-hash-check-seed=true
# Specify the maximum number of peers per torrent.
bt-max-peers=255
# Try to download first and last pieces of each file first. This is useful for previewing files.
bt-prioritize-piece=head
# Removes the unselected files when download is completed in BitTorrent.
bt-remove-unselected-file=true
# Seed previously downloaded files without verifying piece hashes.
bt-seed-unverified=true
# 保存磁力链接元数据为种子文件(.torrent文件), 默认:false
bt-save-metadata=true
# bt-tracker数据来自https://github.com/ngosang/trackerslist/blob/master/trackers_best.txt
bt-tracker=udp://tracker.coppersurfer.tk:6969/announce,udp://tracker.opentrackr.org:1337/announce,udp://tracker.internetwarriors.net:1337/announce,udp://9.rarbg.to:2710/announce,udp://exodus.desync.com:6969/announce,udp://tracker2.itzmx.com:6961/announce,udp://tracker1.itzmx.com:8080/announce,udp://explodie.org:6969/announce,http://tracker.tfile.me:80/announce.php,http://tracker.tfile.me:80/announce,http://tracker.tfile.co:80/announce,http://peersteers.org:80/announce,udp://tracker.tiny-vps.com:6969/announce,udp://ipv4.tracker.harry.lu:80/announce,udp://denis.stalker.upeer.me:6969/announce,udp://tracker.torrent.eu.org:451/announce,udp://tracker.port443.xyz:6969/announce,udp://tracker.cyberia.is:6969/announce,udp://thetracker.org:80/announce,udp://retracker.lanta-net.ru:2710/announce
# Set host and port as an entry point to IPv4 DHT network.
dht-entry-point=dht.transmissionbt.com:6881
# Set host and port as an entry point to IPv6 DHT network.
dht-entry-point6=dht.transmissionbt.com:6881
# Enable IPv4 DHT functionality. It also enables UDP tracker support.
enable-dht=true
# Enable IPv6 DHT functionality.
enable-dht6=true
# Enable Peer Exchange extension.
enable-peer-exchange=true
# Specify the string used during the bitorrent extended handshake for the peer's client version.
peer-agent=Transmission/2.94
# Specify the prefix of peer ID.
peer-id-prefix=-TR2940-
Binary file not shown.
+14
View File
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": [
"./src/renderer/*"
],
"@shared/*": [
"./src/shared/*"
]
}
},
"exclude": ["node_modules", "dist"]
}
-20659
View File
File diff suppressed because it is too large Load Diff
+157 -94
View File
@@ -1,6 +1,6 @@
{
"name": "Motrix",
"version": "1.1.2",
"version": "1.6.11",
"description": "A full-featured download manager",
"homepage": "https://motrix.app",
"author": {
@@ -17,6 +17,7 @@
"scripts": {
"release": "npm run build --publish onTagOrDraft",
"build": "node .electron-vue/build.js && electron-builder",
"build:github": "node .electron-vue/build.js",
"build:dir": "node .electron-vue/build.js && electron-builder --dir",
"build:clean": "cross-env BUILD_TARGET=clean node .electron-vue/build.js",
"build:web": "cross-env BUILD_TARGET=web node .electron-vue/build.js",
@@ -27,11 +28,21 @@
"pack": "npm run pack:main && npm run pack:renderer",
"pack:main": "cross-env NODE_ENV=production webpack --mode production --progress --colors --config .electron-vue/webpack.main.config.js",
"pack:renderer": "cross-env NODE_ENV=production webpack --mode production --progress --colors --config .electron-vue/webpack.renderer.config.js",
"postinstall": "npm run lint:fix"
"postinstall": "electron-builder install-app-deps && npm run lint:fix"
},
"build": {
"productName": "Motrix",
"appId": "net.agalwood.Motrix",
"afterPack": "./build/afterPackHook.js",
"afterSign": "electron-builder-notarize",
"fileAssociations": [
{
"ext": "torrent",
"mimeType": "application/x-bittorrent",
"name": "Torrent",
"role": "Viewer"
}
],
"asar": true,
"directories": {
"output": "release"
@@ -39,6 +50,27 @@
"files": [
"dist/electron/**/*"
],
"protocols": [
{
"name": "Motrix Protocol",
"schemes": [
"mo",
"motrix"
]
},
{
"name": "Magnet Protocol",
"schemes": [
"magnet"
]
},
{
"name": "Thunder Protocol",
"schemes": [
"thunder"
]
}
],
"dmg": {
"window": {
"width": 540,
@@ -60,11 +92,24 @@
},
"mac": {
"target": [
"dmg",
"zip"
{
"target": "dmg",
"arch": [
"x64",
"arm64"
]
},
{
"target": "zip",
"arch": [
"x64",
"arm64"
]
}
],
"type": "distribution",
"darkModeSupport": true,
"hardenedRuntime": true,
"extraResources": {
"from": "./extra/darwin/",
"to": "./",
@@ -72,25 +117,31 @@
"**/*"
]
},
"binaries": [
"./release/mac/Motrix.app/Contents/Resources/engine/aria2c"
],
"category": "public.app-category.utilities",
"protocols": [
{
"name": "Motrix Protocol",
"schemes": [
"mo",
"motrix"
]
}
]
"category": "public.app-category.utilities"
},
"win": {
"target": [
"nsis",
"zip",
"portable"
{
"target": "nsis",
"arch": [
"x64",
"ia32"
]
},
{
"target": "zip",
"arch": [
"x64",
"ia32"
]
},
{
"target": "portable",
"arch": [
"x64",
"ia32"
]
}
],
"extraResources": {
"from": "./extra/win32/",
@@ -105,11 +156,12 @@
"allowToChangeInstallationDirectory": true
},
"linux": {
"category": "Network",
"target": [
"AppImage",
"deb",
"snap",
"pacman",
"AppImage"
"rpm",
"snap"
],
"extraResources": {
"from": "./extra/linux/",
@@ -119,10 +171,21 @@
]
}
},
"snap": {
"publish": [
{
"provider": "github"
},
{
"provider": "snapStore",
"channel": "edge"
}
]
},
"publish": [
{
"provider": "generic",
"url": "https://motrix.app/release/"
"url": "https://dl.motrix.app/release/"
},
{
"provider": "github"
@@ -130,83 +193,83 @@
]
},
"dependencies": {
"@panter/vue-i18next": "^0.15.0",
"aria2": "^4.0.3",
"axios": "^0.18.0",
"clipboard-polyfill": "^2.7.0",
"electron-debug": "^2.1.0",
"@babel/runtime": "^7.14.0",
"@motrix/nat-api": "^0.3.1",
"@panter/vue-i18next": "^0.15.2",
"axios": "^0.21.1",
"bittorrent-peerid": "^1.3.3",
"blob-util": "^2.0.2",
"clipboard-polyfill": "^3.0.3",
"electron-debug": "^3.2.0",
"electron-is": "^3.0.0",
"electron-log": "^2.2.17",
"electron-updater": "^4.0.7",
"element-ui": "^2.5.4",
"forever-monitor": "^1.7.1",
"i18next": "^15.0.0",
"lodash": "^4.17.11",
"electron-log": "^4.3.5",
"electron-store": "^8.0.0",
"electron-updater": "^4.3.9",
"element-ui": "^2.15.1",
"i18next": "^20.2.4",
"lodash": "^4.17.21",
"node-fetch": "^2.6.1",
"normalize.css": "^8.0.1",
"parse-torrent": "^6.1.2",
"parse-torrent": "^9.1.3",
"randomatic": "^3.1.1",
"svg-innerhtml": "^1.1.0",
"vue": "^2.6.4",
"vue": "^2.6.12",
"vue-electron": "^1.0.6",
"vue-router": "^3.0.2",
"vuex": "^3.1.0",
"vuex-router-sync": "^5.0.0"
"vue-router": "^3.5.1",
"vuex": "^3.6.2",
"vuex-router-sync": "^5.0.0",
"ws": "^7.4.5"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.4.0",
"@vue/cli-plugin-eslint": "^3.4.0",
"@vue/cli-service": "^3.4.0",
"@vue/eslint-config-standard": "^4.0.0",
"ajv": "^6.9.1",
"babel-core": "^6.26.3",
"babel-eslint": "^10.0.1",
"babel-loader": "^7.1.4",
"@babel/core": "^7.14.2",
"@babel/plugin-proposal-class-properties": "^7.13.0",
"@babel/plugin-transform-runtime": "^7.14.2",
"@babel/preset-env": "^7.14.2",
"@babel/register": "^7.13.16",
"@electron/remote": "^1.1.0",
"@motrix/multispinner": "^0.2.2",
"@vue/eslint-config-standard": "^6.0.0",
"ajv": "^8.4.0",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.2.2",
"babel-plugin-component": "^1.1.1",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.7.0",
"babel-preset-stage-0": "^6.24.1",
"babel-register": "^6.26.0",
"babili-webpack-plugin": "^0.1.2",
"cfonts": "^2.4.2",
"chalk": "^2.4.1",
"copy-webpack-plugin": "^4.6.0",
"cross-env": "^5.1.6",
"css-loader": "^1.0.1",
"del": "^3.0.0",
"devtron": "^1.4.0",
"electron": "^4.0.4",
"electron-builder": "^20.38.5",
"electron-devtools-installer": "^2.2.4",
"electron-notarize": "^0.0.5",
"electron-osx-sign": "^0.4.11",
"electron-store": "^2.0.0",
"eslint": "^5.13.0",
"eslint-config-standard": "^12.0.0",
"cfonts": "^2.9.2",
"chalk": "^4.1.1",
"copy-webpack-plugin": "^8.1.1",
"cross-env": "^7.0.3",
"css-loader": "^5.2.4",
"css-minimizer-webpack-plugin": "^3.0.0",
"del": "^6.0.0",
"electron": "^11.4.5",
"electron-builder": "22.10.5",
"electron-builder-notarize": "^1.2.0",
"electron-devtools-installer": "^3.2.0",
"electron-notarize": "^1.0.0",
"electron-osx-sign": "^0.5.0",
"eslint": "^7.26.0",
"eslint-friendly-formatter": "^4.0.1",
"eslint-loader": "^2.1.2",
"eslint-plugin-import": "^2.16.0",
"eslint-plugin-node": "^7.0.1",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^5.1.0",
"file-loader": "^2.0.0",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "0.5.0",
"multispinner": "^0.2.1",
"node-loader": "^0.6.0",
"node-sass": "^4.10.0",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"url-loader": "^1.1.2",
"eslint-plugin-html": "^4.0.6",
"vue-html-loader": "^1.2.4",
"vue-loader": "^15.6.2",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.6.4",
"webpack": "^4.29.3",
"webpack-cli": "^3.2.3",
"webpack-dev-server": "^3.1.14",
"webpack-hot-middleware": "^2.24.3",
"webpack-merge": "^4.1.4"
"eslint-plugin-import": "^2.23.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-vue": "^7.9.0",
"eslint-webpack-plugin": "^2.5.4",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.3.1",
"mini-css-extract-plugin": "1.6.0",
"node-loader": "^2.0.0",
"sass": "^1.32.13",
"sass-loader": "^11.1.1",
"style-loader": "^2.0.0",
"terser-webpack-plugin": "^5.1.2",
"url-loader": "^4.1.1",
"vue-loader": "^15.9.7",
"vue-style-loader": "^4.1.3",
"vue-template-compiler": "^2.6.12",
"webpack": "^5.37.0",
"webpack-cli": "^4.7.0",
"webpack-dev-server": "^3.11.2",
"webpack-hot-middleware": "^2.25.0",
"webpack-merge": "^5.7.3",
"worker-loader": "^3.0.8"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

+5 -3
View File
@@ -23,9 +23,11 @@
</section>
</div>
<!-- Set `__static` path to static files in production -->
<script>
if (process.env.NODE_ENV !== 'development') window.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
</script>
<% if (!htmlWebpackPlugin.options.isBrowser && !htmlWebpackPlugin.options.isDev) { %>
<script>
window.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
</script>
<% } %>
<!-- webpack builds are automatically injected -->
</body>
+642 -59
View File
@@ -1,44 +1,71 @@
import { EventEmitter } from 'events'
import { app, shell, dialog, ipcMain } from 'electron'
import is from 'electron-is'
import { readFile, unlink } from 'fs'
import { extname, basename } from 'path'
import { isEmpty } from 'lodash'
import {
APP_RUN_MODE,
AUTO_SYNC_TRACKER_INTERVAL,
AUTO_CHECK_UPDATE_INTERVAL
} from '@shared/constants'
import { checkIsNeedRun } from '@shared/utils'
import {
convertTrackerDataToComma,
fetchBtTrackerFromSource
} from '@shared/utils/tracker'
import logger from './core/Logger'
import ExceptionHandler from './core/ExceptionHandler'
import ConfigManager from './core/ConfigManager'
import { setupLocaleManager } from './ui/Locale'
import Engine from './core/Engine'
import EngineClient from './core/EngineClient'
import UPnPManager from './core/UPnPManager'
import AutoLaunchManager from './core/AutoLaunchManager'
import UpdateManager from './core/UpdateManager'
import EnergyManager from './core/EnergyManager'
import ProtocolManager from './core/ProtocolManager'
import WindowManager from './ui/WindowManager'
import MenuManager from './ui/MenuManager'
import TouchBarManager from './ui/TouchBarManager'
import TrayManager from './ui/TrayManager'
import DockManager from './ui/DockManager'
import ThemeManager from './ui/ThemeManager'
import { getSessionPath } from './utils'
export default class Application extends EventEmitter {
constructor () {
super()
this.exceptionHandler = new ExceptionHandler()
this.isReady = false
this.init()
}
init () {
this.configManager = new ConfigManager()
this.configManager = this.initConfigManager()
this.locale = this.configManager.getLocale()
this.localeManager = setupLocaleManager(this.locale)
this.i18n = this.localeManager.getI18n()
this.windowManager = new WindowManager({
userConfig: this.configManager.getUserConfig()
})
this.setupApplicationMenu()
this.initWindowManager()
this.initUPnPManager()
this.engine = new Engine({
systemConfig: this.configManager.getSystemConfig(),
userConfig: this.configManager.getUserConfig()
})
this.startEngine()
this.menuManager = new MenuManager()
this.menuManager.setup(this.locale)
this.initEngineClient()
this.touchBarManager = new TouchBarManager()
this.initTouchBarManager()
this.initThemeManager()
this.initTrayManager()
this.initDockManager()
this.autoLaunchManager = new AutoLaunchManager()
this.energyManager = new EnergyManager()
@@ -47,43 +74,373 @@ export default class Application extends EventEmitter {
this.initProtocolManager()
this.handleCommands()
this.handleEvents()
this.handleIpcMessages()
this.handleIpcInvokes()
this.emit('application:initialized')
}
initConfigManager () {
this.configListeners = {}
return new ConfigManager()
}
offConfigListeners () {
try {
Object.keys(this.configListeners).forEach((key) => {
this.configListeners[key]()
})
} catch (e) {
logger.warn('[Motrix] offConfigListeners===>', e)
}
this.configListeners = {}
}
setupApplicationMenu () {
this.menuManager = new MenuManager()
this.menuManager.setup(this.locale)
}
adjustMenu () {
if (is.mas()) {
const visibleStates = {
'app.check-for-updates': false,
'task.new-bt-task': false
}
this.menuManager.updateMenuStates(visibleStates, null, null)
this.trayManager.updateMenuStates(visibleStates, null, null)
}
}
startEngine () {
const self = this
try {
this.engine = new Engine({
systemConfig: this.configManager.getSystemConfig(),
userConfig: this.configManager.getUserConfig()
})
this.engine.start()
} catch (err) {
const { message } = err
dialog.showMessageBox({
type: 'error',
title: '系统错误',
message: `应用启动失败:${err.message}`,
buttons: ['知道了'],
cancelId: 1
}, () => {
title: this.i18n.t('app.system-error-title'),
message: this.i18n.t('app.system-error-message', { message })
}).then(_ => {
setTimeout(() => {
app.quit()
self.quit()
}, 100)
})
}
}
start (page) {
this.showPage(page)
async stopEngine () {
try {
await this.engineClient.shutdown({ force: true })
setImmediate(() => {
this.engine.stop()
})
} catch (err) {
logger.warn('[Motrix] shutdown engine fail: ', err.message)
} finally {
// no finally
}
}
showPage (page) {
const win = this.windowManager.openWindow(page)
this.touchBarManager.setup(page, win)
initEngineClient () {
const port = this.configManager.getSystemConfig('rpc-listen-port')
const secret = this.configManager.getSystemConfig('rpc-secret')
this.engineClient = new EngineClient({
port,
secret
})
}
initTrayManager () {
this.trayManager = new TrayManager({
theme: this.configManager.getUserConfig('tray-theme'),
systemTheme: this.themeManager.getSystemTheme(),
speedometer: this.configManager.getUserConfig('tray-speedometer')
})
this.watchTraySpeedometerEnabledChange()
this.trayManager.on('mouse-down', ({ focused }) => {
this.sendCommandToAll('application:update-tray-focused', { focused })
})
this.trayManager.on('mouse-up', ({ focused }) => {
this.sendCommandToAll('application:update-tray-focused', { focused })
})
this.trayManager.on('drop-files', (files = []) => {
this.handleFile(files[0])
})
this.trayManager.on('drop-text', (text) => {
this.handleProtocol(text)
})
}
watchTraySpeedometerEnabledChange () {
const { userConfig } = this.configManager
const key = 'tray-speedometer'
this.configListeners[key] = userConfig.onDidChange('tray-speedometer', async (newValue, oldValue) => {
logger.info('[Motrix] detected tray speedometer value change event:', newValue, oldValue)
this.trayManager.handleSpeedometerEnableChange(newValue)
})
}
initDockManager () {
this.dockManager = new DockManager({
runMode: this.configManager.getUserConfig('run-mode')
})
}
initUPnPManager () {
this.upnp = new UPnPManager()
this.watchUPnPEnabledChange()
this.watchUPnPPortsChange()
const enabled = this.configManager.getUserConfig('enable-upnp')
if (!enabled) {
return
}
this.startUPnPMapping()
}
async startUPnPMapping () {
const btPort = this.configManager.getSystemConfig('listen-port')
const dhtPort = this.configManager.getSystemConfig('dht-listen-port')
const promises = [
this.upnp.map(btPort),
this.upnp.map(dhtPort)
]
try {
await Promise.allSettled(promises)
} catch (e) {
logger.warn('[Motrix] start UPnP mapping fail', e)
}
}
async stopUPnPMapping () {
const btPort = this.configManager.getSystemConfig('listen-port')
const dhtPort = this.configManager.getSystemConfig('dht-listen-port')
const promises = [
this.upnp.unmap(btPort),
this.upnp.unmap(dhtPort)
]
try {
await Promise.allSettled(promises)
} catch (e) {
logger.warn('[Motrix] stop UPnP mapping fail', e)
}
}
watchUPnPPortsChange () {
const { systemConfig } = this.configManager
const watchKeys = ['listen-port', 'dht-listen-port']
watchKeys.forEach((key) => {
this.configListeners[key] = systemConfig.onDidChange(key, async (newValue, oldValue) => {
logger.info('[Motrix] detected port change event:', key, newValue, oldValue)
const enable = this.configManager.getUserConfig('enable-upnp')
if (!enable) {
return
}
const promises = [
this.upnp.unmap(oldValue),
this.upnp.map(newValue)
]
try {
await Promise.allSettled(promises)
} catch (e) {
logger.info('[Motrix] change UPnP port mapping failed:', e)
}
})
})
}
watchUPnPEnabledChange () {
const { userConfig } = this.configManager
const key = 'enable-upnp'
this.configListeners[key] = userConfig.onDidChange(key, async (newValue, oldValue) => {
logger.info('[Motrix] detected enable-upnp value change event:', newValue, oldValue)
if (newValue) {
this.startUPnPMapping()
} else {
await this.stopUPnPMapping()
this.upnp.closeClient()
}
})
}
async shutdownUPnPManager () {
const enable = this.configManager.getUserConfig('enable-upnp')
if (enable) {
await this.stopUPnPMapping()
}
this.upnp.closeClient()
}
autoSyncTracker () {
const enable = this.configManager.getUserConfig('auto-sync-tracker')
const lastTime = this.configManager.getUserConfig('last-sync-tracker-time')
const result = checkIsNeedRun(enable, lastTime, AUTO_SYNC_TRACKER_INTERVAL)
logger.info('[Motrix] auto sync tracker checkIsNeedRun:', result)
if (!result) {
return
}
const source = this.configManager.getUserConfig('tracker-source')
if (isEmpty(source)) {
return
}
setTimeout(() => {
fetchBtTrackerFromSource(source).then((data) => {
logger.warn('[Motrix] auto sync tracker data:', data)
if (!data || data.length === 0) {
return
}
const tracker = convertTrackerDataToComma(data)
this.savePreference({
system: {
'bt-tracker': tracker
},
user: {
'last-sync-tracker-time': Date.now()
}
})
}).catch((err) => {
logger.warn('[Motrix] auto sync tracker failed:', err.message)
})
}, 500)
}
autoResumeTask () {
const enabled = this.configManager.getUserConfig('resume-all-when-app-launched')
if (!enabled) {
return
}
this.engineClient.call('unpauseAll')
}
initWindowManager () {
this.windowManager = new WindowManager({
userConfig: this.configManager.getUserConfig()
})
this.windowManager.on('window-resized', (data) => {
this.storeWindowState(data)
})
this.windowManager.on('window-moved', (data) => {
this.storeWindowState(data)
})
this.windowManager.on('window-closed', (data) => {
this.storeWindowState(data)
})
this.windowManager.on('enter-full-screen', (window) => {
this.dockManager.show()
})
this.windowManager.on('leave-full-screen', (window) => {
const mode = this.configManager.getUserConfig('run-mode')
if (mode !== APP_RUN_MODE.STANDARD) {
this.dockManager.hide()
}
})
}
storeWindowState (data = {}) {
const enabled = this.configManager.getUserConfig('keep-window-state')
if (!enabled) {
return
}
const state = this.configManager.getUserConfig('window-state', {})
const { page, bounds } = data
const newState = {
...state,
[page]: bounds
}
this.configManager.setUserConfig('window-state', newState)
}
start (page, options = {}) {
const win = this.showPage(page, options)
win.once('ready-to-show', () => {
this.isReady = true
this.emit('ready')
})
if (is.macOS()) {
this.touchBarManager.setup(page, win)
}
}
showPage (page, options = {}) {
const { openedAtLogin } = options
const autoHideWindow = this.configManager.getUserConfig('auto-hide-window')
return this.windowManager.openWindow(page, {
hidden: openedAtLogin || autoHideWindow
})
}
show (page = 'index') {
this.windowManager.showWindow(page)
}
hide (page) {
if (page) {
this.windowManager.hideWindow(page)
} else {
this.windowManager.hideAllWindow()
}
}
toggle (page = 'index') {
this.windowManager.toggleWindow(page)
}
closePage (page) {
this.windowManager.destroyWindow(page)
}
stop () {
this.engine.stop()
this.energyManager.stopPowerSaveBlocker()
async stop () {
try {
await this.shutdownUPnPManager()
this.energyManager.stopPowerSaveBlocker()
await this.stopEngine()
this.trayManager.destroy()
} catch (err) {
logger.warn('[Motrix] stop error: ', err.message)
}
}
async quit () {
await this.stop()
app.exit()
}
sendCommand (command, ...args) {
@@ -109,32 +466,78 @@ export default class Application extends EventEmitter {
})
}
initProtocolManager () {
if (is.dev() || is.mas()) {
initThemeManager () {
this.themeManager = new ThemeManager()
this.themeManager.on('system-theme-change', (theme) => {
this.trayManager.handleSystemThemeChange(theme)
this.sendCommandToAll('application:update-system-theme', { theme })
})
}
initTouchBarManager () {
if (!is.macOS()) {
return
}
this.protocolManager = new ProtocolManager()
this.touchBarManager = new TouchBarManager()
}
initProtocolManager () {
const protocols = this.configManager.getUserConfig('protocols', {})
this.protocolManager = new ProtocolManager({
protocols
})
}
handleProtocol (url) {
if (is.dev() || is.mas()) {
this.show()
this.protocolManager.handle(url)
}
handleFile (filePath) {
if (!filePath) {
return
}
this.protocolManager.handle(url)
this.showPage('index')
if (extname(filePath).toLowerCase() !== '.torrent') {
return
}
this.show()
const name = basename(filePath)
readFile(filePath, (err, data) => {
if (err) {
logger.warn(`[Motrix] read file error: ${filePath}`, err.message)
return
}
const dataURL = Buffer.from(data).toString('base64')
this.sendCommandToAll('application:new-bt-task-with-file', {
name,
dataURL
})
})
}
initUpdaterManager () {
if (is.mas()) {
return
}
this.updateManager = new UpdateManager()
const enabled = this.configManager.getUserConfig('auto-check-update')
const lastTime = this.configManager.getUserConfig('last-check-update-time')
this.updateManager = new UpdateManager({
autoCheck: checkIsNeedRun(enabled, lastTime, AUTO_CHECK_UPDATE_INTERVAL)
})
this.handleUpdaterEvents()
}
handleUpdaterEvents () {
this.updateManager.on('checking', (event) => {
this.menuManager.updateMenuItemEnabledState('app.check-for-updates', false)
this.trayManager.updateMenuItemEnabledState('app.check-for-updates', false)
this.configManager.setUserConfig('last-check-update-time', Date.now())
})
this.updateManager.on('download-progress', (event) => {
@@ -144,51 +547,102 @@ export default class Application extends EventEmitter {
this.updateManager.on('update-not-available', (event) => {
this.menuManager.updateMenuItemEnabledState('app.check-for-updates', true)
this.trayManager.updateMenuItemEnabledState('app.check-for-updates', true)
})
this.updateManager.on('update-downloaded', (event) => {
this.menuManager.updateMenuItemEnabledState('app.check-for-updates', true)
this.trayManager.updateMenuItemEnabledState('app.check-for-updates', true)
const win = this.windowManager.getWindow('index')
win.setProgressBar(0)
})
this.updateManager.on('will-updated', (event) => {
this.updateManager.on('will-updated', async (event) => {
this.windowManager.setWillQuit(true)
await this.stop()
})
this.updateManager.on('update-error', (event) => {
this.menuManager.updateMenuItemEnabledState('app.check-for-updates', true)
this.trayManager.updateMenuItemEnabledState('app.check-for-updates', true)
})
}
relaunch (page = 'index') {
this.stop()
async relaunch () {
await this.stop()
app.relaunch()
app.exit()
// this.closePage(page)
// if (page === 'index') {
// this.engine.restart()
// }
// setTimeout(() => {
// this.showPage(page)
// }, 500)
}
async resetSession () {
await this.stopEngine()
app.clearRecentDocuments()
const sessionPath = this.configManager.getUserConfig('session-path') || getSessionPath()
setTimeout(() => {
unlink(sessionPath, function (err) {
logger.info('[Motrix] Removed the download seesion file:', err)
})
this.engine.start()
}, 3000)
}
savePreference (config = {}) {
logger.info('[Motrix] save preference:', config)
const { system, user } = config
if (!isEmpty(system)) {
console.info('[Motrix] main save system config: ', system)
this.configManager.setSystemConfig(system)
this.engineClient.changeGlobalOption(system)
}
if (!isEmpty(user)) {
console.info('[Motrix] main save user config: ', user)
this.configManager.setUserConfig(user)
}
}
handleCommands () {
this.on('application:save-preference', this.savePreference)
this.on('application:update-tray', (tray) => {
this.trayManager.updateTrayByImage(tray)
})
this.on('application:relaunch', () => {
this.relaunch()
})
this.on('application:exit', () => {
this.engine.stop()
app.exit()
this.on('application:quit', () => {
this.quit()
})
this.on('application:show', (page = 'index') => {
this.showPage(page)
this.on('application:open-at-login', (openAtLogin) => {
if (is.linux()) {
return
}
if (openAtLogin) {
this.autoLaunchManager.enable()
} else {
this.autoLaunchManager.disable()
}
})
this.on('application:show', ({ page }) => {
this.show(page)
})
this.on('application:hide', ({ page }) => {
this.hide(page)
})
this.on('application:reset-session', () => this.resetSession())
this.on('application:reset', () => {
this.offConfigListeners()
this.configManager.reset()
this.relaunch()
})
@@ -197,39 +651,168 @@ export default class Application extends EventEmitter {
this.updateManager.check()
})
this.on('application:change-theme', (theme) => {
this.themeManager.updateSystemTheme(theme)
this.sendCommandToAll('application:update-theme', { theme })
})
this.on('application:change-locale', (locale) => {
this.menuManager.setup(locale)
this.localeManager.changeLanguageByLocale(locale)
.then(() => {
this.menuManager.handleLocaleChange(locale)
this.trayManager.handleLocaleChange(locale)
})
})
this.on('application:toggle-dock', (visible) => {
if (visible) {
this.dockManager.show()
} else {
this.dockManager.hide()
// Hiding the dock icon will trigger the entire app to hide.
this.show()
}
})
this.on('application:auto-hide-window', (hide) => {
if (hide) {
this.windowManager.handleWindowBlur()
} else {
this.windowManager.unbindWindowBlur()
}
})
this.on('application:change-menu-states', (visibleStates, enabledStates, checkedStates) => {
this.menuManager.updateMenuStates(visibleStates, enabledStates, checkedStates)
this.trayManager.updateMenuStates(visibleStates, enabledStates, checkedStates)
})
this.on('application:open-file', (event) => {
dialog.showOpenDialog({
properties: ['openFile'],
filters: [
{
name: 'Torrent',
extensions: ['torrent']
}
]
}).then(({ canceled, filePaths }) => {
if (canceled || filePaths.length === 0) {
return
}
const [filePath] = filePaths
this.handleFile(filePath)
})
})
this.on('application:clear-recent-tasks', () => {
app.clearRecentDocuments()
})
this.on('application:setup-protocols-client', (protocols) => {
if (is.dev() || is.mas()) {
return
}
logger.info('[Motrix] setup protocols client:', protocols)
this.protocolManager.setup(protocols)
})
this.on('application:open-external', (url) => {
this.openExternal(url)
})
this.on('help:official-website', () => {
const url = 'https://motrix.app/'
shell.openExternal(url)
this.openExternal(url)
})
this.on('help:manual', () => {
const url = 'https://motrix.app/manual'
shell.openExternal(url)
this.openExternal(url)
})
this.on('help:release-notes', () => {
const url = 'https://motrix.app/release'
shell.openExternal(url)
this.openExternal(url)
})
this.on('help:report-problem', () => {
const url = 'https://motrix.app/report'
shell.openExternal(url)
this.openExternal(url)
})
}
openExternal (url) {
if (!url) {
return
}
shell.openExternal(url)
}
handleConfigChange (configName) {
this.sendCommandToAll('application:update-preference-config', { configName })
}
handleEvents () {
this.once('application:initialized', () => {
this.autoSyncTracker()
this.autoResumeTask()
this.adjustMenu()
})
this.configManager.userConfig.onDidAnyChange(() => this.handleConfigChange('user'))
this.configManager.systemConfig.onDidAnyChange(() => this.handleConfigChange('system'))
this.on('download-status-change', (downloading) => {
this.trayManager.handleDownloadStatusChange(downloading)
if (downloading) {
this.energyManager.startPowerSaveBlocker()
} else {
this.energyManager.stopPowerSaveBlocker()
}
})
this.on('speed-change', (speed) => {
this.dockManager.handleSpeedChange(speed)
this.trayManager.handleSpeedChange(speed)
})
this.on('task-download-complete', (task, path) => {
this.dockManager.openDock(path)
if (is.linux()) {
return
}
app.addRecentDocument(path)
})
}
handleIpcMessages () {
ipcMain.on('command', (event, command, ...args) => {
logger.log('receive command', command, ...args)
logger.log('[Motrix] ipc receive command', command, ...args)
this.emit(command, ...args)
})
ipcMain.on('update-menu-states', (event, visibleStates, enabledStates, checkedStates) => {
this.menuManager.updateStates(visibleStates, enabledStates, checkedStates)
ipcMain.on('event', (event, eventName, ...args) => {
logger.log('[Motrix] ipc receive event', eventName, ...args)
this.emit(eventName, ...args)
})
}
handleIpcInvokes () {
ipcMain.handle('get-app-config', async () => {
const systemConfig = this.configManager.getSystemConfig()
const userConfig = this.configManager.getUserConfig()
const result = {
...systemConfig,
...userConfig
}
return result
})
}
}
+183
View File
@@ -0,0 +1,183 @@
import { EventEmitter } from 'events'
import { app } from 'electron'
import is from 'electron-is'
import ExceptionHandler from './core/ExceptionHandler'
import logger from './core/Logger'
import Application from './Application'
import {
splitArgv,
parseArgvAsUrl,
parseArgvAsFile
} from './utils'
import { EMPTY_STRING } from '@shared/constants'
export default class Launcher extends EventEmitter {
constructor () {
super()
this.url = EMPTY_STRING
this.file = EMPTY_STRING
this.makeSingleInstance(() => {
this.init()
})
}
makeSingleInstance (callback) {
// Mac App Store Sandboxed App not support requestSingleInstanceLock
if (is.mas()) {
callback && callback()
return
}
const gotSingleLock = app.requestSingleInstanceLock()
if (!gotSingleLock) {
app.quit()
} else {
app.on('second-instance', (event, argv, workingDirectory) => {
global.application.showPage('index')
if (!is.macOS() && argv.length > 1) {
this.handleAppLaunchArgv(argv)
}
})
callback && callback()
}
}
init () {
this.exceptionHandler = new ExceptionHandler()
this.openedAtLogin = is.macOS()
? app.getLoginItemSettings().wasOpenedAtLogin
: false
if (process.argv.length > 1) {
this.handleAppLaunchArgv(process.argv)
}
logger.info('[Motrix] openedAtLogin:', this.openedAtLogin)
this.handleAppEvents()
}
handleAppEvents () {
this.handleOpenUrl()
this.handleOpenFile()
this.handelAppReady()
this.handleAppWillQuit()
}
/**
* handleOpenUrl
* Event 'open-url' macOS only
* "name": "Motrix Protocol",
* "schemes": ["mo", "motrix"]
*/
handleOpenUrl () {
if (is.mas() || !is.macOS()) {
return
}
app.on('open-url', (event, url) => {
logger.info(`[Motrix] open-url: ${url}`)
event.preventDefault()
this.url = url
this.sendUrlToApplication()
})
}
/**
* handleOpenFile
* Event 'open-file' macOS only
* handle open torrent file
*/
handleOpenFile () {
if (!is.macOS()) {
return
}
app.on('open-file', (event, path) => {
logger.info(`[Motrix] open-file: ${path}`)
event.preventDefault()
this.file = path
this.sendFileToApplication()
})
}
/**
* handleAppLaunchArgv
* For Windows, Linux
* @param {array} argv
*/
handleAppLaunchArgv (argv) {
logger.info('[Motrix] handleAppLaunchArgv:', argv)
// args: array, extra: map
const { args, extra } = splitArgv(argv)
logger.info('[Motrix] split argv args:', args)
logger.info('[Motrix] split argv extra:', extra)
if (extra['--opened-at-login'] === '1') {
this.openedAtLogin = true
}
const file = parseArgvAsFile(args)
if (file) {
this.file = file
this.sendFileToApplication()
}
const url = parseArgvAsUrl(args)
if (url) {
this.url = url
this.sendUrlToApplication()
}
}
sendUrlToApplication () {
if (this.url && global.application && global.application.isReady) {
global.application.handleProtocol(this.url)
this.url = EMPTY_STRING
}
}
sendFileToApplication () {
if (this.file && global.application && global.application.isReady) {
global.application.handleFile(this.file)
this.file = EMPTY_STRING
}
}
handelAppReady () {
app.on('ready', () => {
global.application = new Application()
const { openedAtLogin } = this
global.application.start('index', {
openedAtLogin
})
global.application.on('ready', () => {
this.sendUrlToApplication()
this.sendFileToApplication()
})
})
app.on('activate', () => {
if (global.application) {
logger.info('[Motrix] activate')
global.application.showPage('index')
}
})
}
handleAppWillQuit () {
app.on('will-quit', () => {
logger.info('[Motrix] will-quit')
if (global.application) {
global.application.stop()
}
})
}
}
+3 -3
View File
@@ -1,5 +1,5 @@
export default {
'darwin': 'aria2c',
'win32': 'aria2c.exe',
'linux': 'aria2c'
darwin: 'aria2c',
win32: 'aria2c.exe',
linux: 'aria2c'
}
+2 -14
View File
@@ -6,24 +6,12 @@ export default {
title: 'Motrix',
width: 1024,
height: 768,
minWidth: 840,
minWidth: 400,
minHeight: 420,
// backgroundColor: '#FFFFFF',
transparent: !is.windows()
},
bindCloseToHide: true,
url: is.dev() ? `http://localhost:9080` : `file://${__dirname}/index.html`
},
about: {
attrs: {
title: '关于',
width: 580,
height: 320,
backgroundColor: '#FFFFFF',
resizable: false,
minimizable: false,
maximizable: false
},
url: is.dev() ? `http://localhost:9080/about` : `file://${__dirname}/about.html`
url: is.dev() ? 'http://localhost:9080' : require('path').join('file://', __dirname, '/index.html')
}
}
+2
View File
@@ -1,6 +1,8 @@
/* eslint quote-props: ["error", "always"] */
export default {
'task-list': 'application:task-list',
'new-task': 'application:new-task',
'new-bt-task': 'application:new-bt-task',
'pause-all-task': 'application:pause-all-task',
'resume-all-task': 'application:resume-all-task',
'preferences': 'application:preferences',
+34
View File
@@ -0,0 +1,34 @@
import { app } from 'electron'
import { LOGIN_SETTING_OPTIONS } from '@shared/constants'
export default class AutoLaunchManager {
enable () {
return new Promise((resolve, reject) => {
const enabled = app.getLoginItemSettings(LOGIN_SETTING_OPTIONS).openAtLogin
if (enabled) {
resolve()
}
app.setLoginItemSettings({
...LOGIN_SETTING_OPTIONS,
openAtLogin: true
})
resolve()
})
}
disable () {
return new Promise((resolve, reject) => {
app.setLoginItemSettings({ openAtLogin: false })
resolve()
})
}
isEnabled () {
return new Promise((resolve, reject) => {
const enabled = app.getLoginItemSettings(LOGIN_SETTING_OPTIONS).openAtLogin
resolve(enabled)
})
}
}
+116 -23
View File
@@ -1,11 +1,24 @@
import { app } from 'electron'
import is from 'electron-is'
import Store from 'electron-store'
import {
getDhtPath,
getLogPath,
getSessionPath,
getUserDownloadsPath
getUserDownloadsPath,
getMaxConnectionPerServer
} from '../utils/index'
import {
APP_RUN_MODE,
APP_THEME,
EMPTY_STRING,
IP_VERSION,
LOGIN_SETTING_OPTIONS,
NGOSANG_TRACKERS_BEST_IP_URL_CDN,
NGOSANG_TRACKERS_BEST_URL_CDN
} from '@shared/constants'
import { separateConfig } from '@shared/utils'
export default class ConfigManager {
constructor () {
@@ -20,49 +33,129 @@ export default class ConfigManager {
this.initUserConfig()
}
/**
* Some aria2 conf
* https://aria2.github.io/manual/en/html/aria2c.html
*
* Best bt trackers
* @see https://github.com/ngosang/trackerslist
*
* @see https://github.com/XIU2/TrackersListCollection
*/
initSystemConfig () {
this.systemConfig = new Store({
name: 'system',
/* eslint-disable quote-props */
defaults: {
dir: getUserDownloadsPath(),
// 断点续传
continue: true,
pause: true,
split: 16,
'rpc-listen-port': 16800,
'rpc-secret': '',
'all-proxy': EMPTY_STRING,
'allow-overwrite': false,
'auto-file-renaming': true,
'allow-overwrite': true,
'bt-exclude-tracker': EMPTY_STRING,
'bt-load-saved-metadata': true,
'bt-save-metadata': true,
'bt-tracker': EMPTY_STRING,
'continue': true,
'dht-file-path': getDhtPath(IP_VERSION.V4),
'dht-file-path6': getDhtPath(IP_VERSION.V6),
'dht-listen-port': 26701,
'dir': getUserDownloadsPath(),
'listen-port': 21301,
'max-concurrent-downloads': 5,
// macOS 版本修改过源码自己编译的,Linux 和 Windows 版本 暂未处理
'max-connection-per-server': is.macOS() ? 64 : 16,
'min-split-size': '1M',
'max-overall-download-limit': 0,
'max-overall-upload-limit': 0,
'max-connection-per-server': getMaxConnectionPerServer(),
'max-download-limit': 0,
'all-proxy': '',
'max-overall-download-limit': 0,
'max-overall-upload-limit': '256K',
'min-split-size': '1M',
'no-proxy': EMPTY_STRING,
'pause': true,
'rpc-listen-port': 16800,
'rpc-secret': EMPTY_STRING,
'seed-ratio': 1,
'seed-time': 60,
'split': getMaxConnectionPerServer(),
'user-agent': 'Transmission/2.94'
}
/* eslint-enable quote-props */
})
this.fixSystemConfig()
}
initUserConfig () {
this.userConfig = new Store({
name: 'user',
// Schema need electron-store upgrade to 3.x.x,
// but it will cause the application build to fail.
// schema: {
// theme: {
// type: 'string',
// enum: ['auto', 'light', 'dark']
// }
// },
/* eslint-disable quote-props */
defaults: {
'resume-all-when-app-launched': false,
'task-notification': true,
'hide-app-menu': false,
'all-proxy-backup': EMPTY_STRING,
'auto-check-update': is.macOS(),
'auto-hide-window': false,
'auto-sync-tracker': true,
'enable-upnp': true,
'engine-max-connection-per-server': getMaxConnectionPerServer(),
'hide-app-menu': is.windows() || is.linux(),
'keep-seeding': false,
'keep-window-state': false,
'last-check-update-time': 0,
'last-sync-tracker-time': 0,
'locale': app.getLocale(),
'log-path': getLogPath(),
'new-task-show-downloading': true,
'auto-check-for-updates': false,
'no-confirm-before-delete-task': false,
'open-at-login': false,
'protocols': { 'magnet': true, 'thunder': false },
'resume-all-when-app-launched': false,
'run-mode': APP_RUN_MODE.STANDARD,
'session-path': getSessionPath(),
'task-notification': true,
'theme': APP_THEME.AUTO,
'tracker-source': [
NGOSANG_TRACKERS_BEST_IP_URL_CDN,
NGOSANG_TRACKERS_BEST_URL_CDN
],
'tray-theme': APP_THEME.AUTO,
'tray-speedometer': is.macOS(),
'update-channel': 'latest',
'use-proxy': false,
'all-proxy-backup': '',
'log-path': getLogPath(),
'session-path': getSessionPath(),
'locale': app.getLocale()
'window-state': {}
}
/* eslint-enable quote-props */
})
this.fixUserConfig()
}
fixSystemConfig () {
// Remove aria2c unrecognized options
const { others } = separateConfig(this.systemConfig.store)
if (!others) {
return
}
Object.keys(others).forEach(key => {
this.systemConfig.delete(key)
})
}
fixUserConfig () {
// Fix the value of open-at-login when the user delete
// the Motrix self-starting item through startup management.
const openAtLogin = app.getLoginItemSettings(LOGIN_SETTING_OPTIONS).openAtLogin
if (this.getUserConfig('open-at-login') !== openAtLogin) {
this.setUserConfig('open-at-login', openAtLogin)
}
if (this.getUserConfig('tracker-source').length === 0) {
this.setUserConfig('tracker-source', [
NGOSANG_TRACKERS_BEST_IP_URL_CDN,
NGOSANG_TRACKERS_BEST_URL_CDN
])
}
}
getSystemConfig (key, defaultValue) {
+7 -5
View File
@@ -1,6 +1,8 @@
import { powerSaveBlocker } from 'electron'
let psbId = null
import logger from './Logger'
let psbId
export default class EnergyManager {
startPowerSaveBlocker () {
if (psbId && powerSaveBlocker.isStarted(psbId)) {
@@ -8,16 +10,16 @@ export default class EnergyManager {
}
psbId = powerSaveBlocker.start('prevent-app-suspension')
console.log('startPowerSaveBlocker===>', psbId)
logger.info('[Motrix] start power save blocker:', psbId)
}
stopPowerSaveBlocker () {
if (!psbId || !powerSaveBlocker.isStarted(psbId)) {
if (typeof psbId === 'undefined' || !powerSaveBlocker.isStarted(psbId)) {
return
}
powerSaveBlocker.stop(psbId)
console.log('stopPowerSaveBlocker===>', psbId)
psbId = null
logger.info('[Motrix] stop power save blocker:', psbId)
psbId = undefined
}
}
+108 -68
View File
@@ -1,107 +1,147 @@
'use strict'
import { app } from 'electron'
import is from 'electron-is'
import { existsSync } from 'fs'
import { existsSync, writeFile, unlink } from 'fs'
import { resolve, join } from 'path'
import forever from 'forever-monitor'
import { spawn } from 'child_process'
import logger from './Logger'
import { getI18n } from '../ui/Locale'
import {
getEngineBin,
getEnginePidPath,
getSessionPath,
transformConfig
} from '../utils/index'
const { platform } = process
export default class Engine {
// ChildProcess | null
static instance = null
constructor (options = {}) {
this.options = options
this.i18n = getI18n()
this.systemConfig = options.systemConfig
this.userConfig = options.userConfig
this.basePath = this.getBasePath()
}
getStartSh () {
const { platform } = process
let basePath = resolve(app.getAppPath(), '..')
start () {
const pidPath = getEnginePidPath()
logger.info('[Motrix] Engie pid path:', pidPath)
if (this.instance) {
return
}
const binPath = this.getBinPath()
const args = this.getStartArgs()
this.instance = spawn(binPath, args, {
windowsHide: false,
stdio: is.dev() ? 'pipe' : 'ignore'
})
const pid = this.instance.pid.toString()
this.writePidFile(pidPath, pid)
this.instance.once('close', function () {
try {
unlink(pidPath, function (err) {
if (err) {
logger.warn(`[Motrix] Unlink engine process pid file failed: ${err}`)
}
})
} catch (err) {
logger.warn(`[Motrix] Unlink engine process pid file failed: ${err}`)
}
})
if (is.dev()) {
basePath = resolve(__dirname, `../../../extra/${platform}`)
}
this.instance.stdout.on('data', function (data) {
logger.log('[Motrix] engine stdout===>', data.toString())
})
this.instance.stderr.on('data', function (data) {
logger.log('[Motrix] engine stderr===>', data.toString())
})
}
}
stop () {
if (this.instance) {
this.instance.kill()
this.instance = null
}
}
writePidFile (pidPath, pid) {
writeFile(pidPath, pid, (err) => {
if (err) {
logger.error(`[Motrix] Write engine process pid failed: ${err}`)
}
})
}
getBinPath () {
const binName = getEngineBin(platform)
if (!binName) {
throw new Error('引擎已损坏,请重新安装: (')
throw new Error(this.i18n.t('app.engine-damaged-message'))
}
let binPath = join(basePath, `/engine/${binName}`)
const binIsExist = existsSync(binPath)
const result = join(this.basePath, `/engine/${binName}`)
const binIsExist = existsSync(result)
if (!binIsExist) {
logger.error('[Motrix] engine bin is not exist===>', binPath)
throw new Error('引擎文件缺失,请重新安装: (')
logger.error('[Motrix] engine bin is not exist:', result)
throw new Error(this.i18n.t('app.engine-missing-message'))
}
let confPath = join(basePath, '/engine/aria2.conf')
let sessionPath = this.userConfig['session-path'] || getSessionPath()
const sessionIsExist = existsSync(sessionPath)
let result = [`${binPath}`, `--conf-path=${confPath}`, `--save-session=${sessionPath}`]
if (sessionIsExist) {
result = [...result, `--input-file=${sessionPath}`]
}
const extraConfig = transformConfig(this.systemConfig)
result = [...result, ...extraConfig]
return result
}
start () {
const sh = this.getStartSh()
logger.info('[Motrix] Engine start sh===>', sh)
this.instance = forever.start(sh, {
max: 3,
parser: function (command, args) {
return {
command: command,
args: args
}
},
silent: !is.dev()
})
getBasePath () {
let result = resolve(app.getAppPath(), '..')
const { child } = this.instance
logger.info('[Motrix] Engine pid===>', child.pid)
this.instance.on('exit:code', function (code) {
logger.info(`[Motrix] Engine has exited after 3 restarts===> ${code}`)
})
this.instance.on('error', (err) => {
logger.info(`[Motrix] Engine has exited after 3 restarts===> ${err}`)
})
}
stop () {
const { pid } = this.instance.child
try {
logger.info('[Motrix] Engine stopping===>')
this.instance.stop()
logger.info('[Motrix] Engine stopped===>', pid)
} catch (err) {
logger.error('[Motrix] Engine stop fail===>', err.message)
this.forceStop(pid)
} finally {
if (is.dev()) {
result = resolve(__dirname, `../../../extra/${platform}`)
}
return result
}
forceStop (pid) {
getStartArgs () {
const confPath = join(this.basePath, '/engine/aria2.conf')
const sessionPath = this.userConfig['session-path'] || getSessionPath()
const sessionIsExist = existsSync(sessionPath)
let result = [`--conf-path=${confPath}`, `--save-session=${sessionPath}`]
if (sessionIsExist) {
result = [...result, `--input-file=${sessionPath}`]
}
const extraConfig = {
...this.systemConfig
}
const keepSeeding = this.userConfig['keep-seeding']
const seedRatio = this.systemConfig['seed-ratio']
if (keepSeeding || seedRatio === 0) {
extraConfig['seed-ratio'] = 0
delete extraConfig['seed-time']
}
console.log('extraConfig===>', extraConfig)
const extra = transformConfig(extraConfig)
result = [...result, ...extra]
return result
}
isRunning (pid) {
try {
if (pid) {
process.kill(pid)
}
} catch (err) {
logger.warn('[Motrix] Engine forceStop fail===>', err)
return process.kill(pid, 0)
} catch (e) {
return e.code === 'EPERM'
}
}
+70
View File
@@ -0,0 +1,70 @@
'use strict'
import { Aria2 } from '@shared/aria2'
import logger from './Logger'
import {
compactUndefined,
formatOptionsForEngine
} from '@shared/utils'
import {
ENGINE_RPC_HOST,
ENGINE_RPC_PORT,
EMPTY_STRING
} from '@shared/constants'
const defaults = {
host: ENGINE_RPC_HOST,
port: ENGINE_RPC_PORT,
secret: EMPTY_STRING
}
export default class EngineClient {
static instance = null
static client = null
constructor (options = {}) {
this.options = {
...defaults,
...options
}
this.init()
}
init () {
this.connect()
}
connect () {
logger.info('[Motrix] main engine client connect', this.options)
const { host, port, secret } = this.options
this.client = new Aria2({
host,
port,
secret
})
}
async call (method, ...args) {
return this.client.call(method, ...args).catch((err) => {
logger.warn('[Motrix] call client fail:', err.message)
})
}
async changeGlobalOption (options) {
logger.info('[Motrix] change engine global option:', options)
const args = formatOptionsForEngine(options)
return this.call('changeGlobalOption', args)
}
async shutdown (options = {}) {
const { force = false } = options
const { secret } = this.options
const method = force ? 'forceShutdown' : 'shutdown'
const args = compactUndefined([secret])
return this.call(method, ...args)
}
}
+1
View File
@@ -1,5 +1,6 @@
import { app, dialog } from 'electron'
import is from 'electron-is'
import logger from './Logger'
const defaults = {
+3 -2
View File
@@ -1,7 +1,8 @@
import is from 'electron-is'
import logger from 'electron-log'
logger.transports.file.level = is.production() ? 'warn' : 'info'
logger.info('Logger init')
logger.transports.file.level = is.production() ? 'warn' : 'silly'
logger.info('[Motrix] Logger init')
logger.warn('[Motrix] Logger init')
export default logger
+65 -13
View File
@@ -1,31 +1,85 @@
import { EventEmitter } from 'events'
import { app } from 'electron'
import is from 'electron-is'
import { parse } from 'querystring'
import logger from './Logger'
import protocolMap from '../configs/protocol'
import { ADD_TASK_TYPE } from '@shared/constants'
export default class ProtocolManager extends EventEmitter {
constructor (options = {}) {
super()
this.options = options
// package.json:build.protocols[].schemes[]
// options.protocols: { 'magnet': true, 'thunder': false }
this.protocols = {
mo: true,
motrix: true,
...options.protocols
}
this.init()
}
init () {
// package.json:build.mac.protocols[].schemes[]
if (!app.isDefaultProtocolClient('mo')) {
app.setAsDefaultProtocolClient('mo')
}
if (!app.isDefaultProtocolClient('motrix')) {
app.setAsDefaultProtocolClient('motrix')
const { protocols } = this
this.setup(protocols)
}
setup (protocols) {
if (is.dev() || is.mas()) {
return
}
Object.keys(protocols).forEach((protocol) => {
const enabled = protocols[protocol]
if (enabled) {
if (!app.isDefaultProtocolClient(protocol)) {
app.setAsDefaultProtocolClient(protocol)
}
} else {
app.removeAsDefaultProtocolClient(protocol)
}
})
}
handle (url) {
logger.info(`[Motrix] protocol url: ${url}`)
if (
url.toLowerCase().startsWith('ftp:') ||
url.toLowerCase().startsWith('http:') ||
url.toLowerCase().startsWith('https:') ||
url.toLowerCase().startsWith('magnet:') ||
url.toLowerCase().startsWith('thunder:')
) {
return this.handleResourceProtocol(url)
}
if (
url.toLowerCase().startsWith('mo:') ||
url.toLowerCase().startsWith('motrix:')
) {
return this.handleMoProtocol(url)
}
}
handleResourceProtocol (url) {
if (!url) {
return
}
global.application.sendCommandToAll('application:new-task', {
type: ADD_TASK_TYPE.URI,
uri: url
})
}
handleMoProtocol (url) {
const parsed = new URL(url)
const { host } = parsed
const { host, search } = parsed
logger.info('[Motrix] protocol parsed:', parsed, host)
const command = protocolMap[host]
@@ -33,10 +87,8 @@ export default class ProtocolManager extends EventEmitter {
return
}
// @TODO 没想明白怎么传参数好
// 如果按顺序传递,那 url 的 query string 就要求有序的了
// const query = queryString.parse(parsed.query)
const args = []
global.application.sendCommand(command, ...args)
const query = search.startsWith('?') ? search.replace('?', '') : search
const args = parse(query)
global.application.sendCommandToAll(command, args)
}
}
+99
View File
@@ -0,0 +1,99 @@
import NatAPI from '@motrix/nat-api'
import logger from './Logger'
let client = null
const mappingStatus = {}
export default class UPnPManager {
constructor (options = {}) {
this.options = {
...options
}
}
init () {
if (client) {
return
}
client = new NatAPI({
autoUpdate: true
})
}
map (port) {
this.init()
return new Promise((resolve, reject) => {
logger.info('[Motrix] UPnPManager port mapping: ', port)
if (!port) {
reject(new Error('[Motrix] port was not specified'))
return
}
try {
client.map(port, (err) => {
if (err) {
logger.warn(`[Motrix] UPnPManager map ${port} failed, error: `, err)
reject(err.message)
return
}
mappingStatus[port] = true
logger.info(`[Motrix] UPnPManager port ${port} mapping succeeded`)
resolve()
})
} catch (err) {
reject(err.message)
}
})
}
unmap (port) {
this.init()
return new Promise((resolve, reject) => {
logger.info('[Motrix] UPnPManager port unmapping: ', port)
if (!port) {
reject(new Error('[Motrix] port was not specified'))
return
}
if (!mappingStatus[port]) {
resolve()
return
}
try {
client.unmap(port, (err) => {
if (err) {
logger.warn(`[Motrix] UPnPManager unmap ${port} failed, error: `, err)
reject(err.message)
return
}
logger.info(`[Motrix] UPnPManager port ${port} unmapping succeeded`)
mappingStatus[port] = false
resolve()
})
} catch (err) {
reject(err.message)
}
})
}
closeClient () {
if (!client) {
return
}
try {
client.destroy(() => {
client = null
})
} catch (err) {
logger.warn('[Motrix] close UPnP client fail', err)
}
}
}
+47 -18
View File
@@ -1,9 +1,11 @@
import { EventEmitter } from 'events'
import { resolve } from 'path'
import { dialog } from 'electron'
import is from 'electron-is'
import { autoUpdater } from 'electron-updater'
import { resolve } from 'path'
import logger from './Logger'
import { getI18n } from '../ui/Locale'
if (is.dev()) {
autoUpdater.updateConfigPath = resolve(__dirname, '../../../app-update.yml')
@@ -13,10 +15,17 @@ export default class UpdateManager extends EventEmitter {
constructor (options = {}) {
super()
this.options = options
this.i18n = getI18n()
this.isChecking = false
this.updater = autoUpdater
this.updater.autoDownload = false
this.updater.autoInstallOnAppQuit = false
this.updater.logger = logger
this.autoCheckData = {
checkEnable: this.options.autoCheck,
userCheck: false
}
this.init()
}
@@ -33,14 +42,22 @@ export default class UpdateManager extends EventEmitter {
this.updater.on('update-not-available', this.updateNotAvailable.bind(this))
this.updater.on('download-progress', this.updateDownloadProgress.bind(this))
this.updater.on('update-downloaded', this.updateDownloaded.bind(this))
this.updater.on('update-cancelled', this.updateCancelled.bind(this))
this.updater.on('error', this.updateError.bind(this))
if (this.autoCheckData.checkEnable && !this.isChecking) {
this.autoCheckData.userCheck = false
this.updater.checkForUpdates()
}
}
check () {
this.autoCheckData.userCheck = true
this.updater.checkForUpdates()
}
checkingForUpdate () {
this.isChecking = true
this.emit('checking')
}
@@ -48,23 +65,26 @@ export default class UpdateManager extends EventEmitter {
this.emit('update-available', info)
dialog.showMessageBox({
type: 'info',
title: '发现新版本',
message: '发现新版本,是否现在更新?',
buttons: ['是', '否'],
title: this.i18n.t('app.check-for-updates-title'),
message: this.i18n.t('app.update-available-message'),
buttons: [this.i18n.t('app.yes'), this.i18n.t('app.no')],
cancelId: 1
}, (buttonIndex) => {
if (buttonIndex === 0) {
}).then(({ response }) => {
if (response === 0) {
this.updater.downloadUpdate()
}
})
}
updateNotAvailable (event, info) {
this.isChecking = false
this.emit('update-not-available', info)
dialog.showMessageBox({
title: '没有更新的版本',
message: '您目前使用的已是最新版本'
})
if (this.autoCheckData.userCheck) {
dialog.showMessageBox({
title: this.i18n.t('app.check-for-updates-title'),
message: this.i18n.t('app.update-not-available-message')
})
}
}
/**
@@ -84,20 +104,29 @@ export default class UpdateManager extends EventEmitter {
this.emit('update-downloaded', info)
this.updater.logger.log(`Update Downloaded: ${info}`)
dialog.showMessageBox({
title: '安装更新',
message: '更新下载完成,应用程序将退出并开始更新...'
}, () => {
title: this.i18n.t('app.check-for-updates-title'),
message: this.i18n.t('app.update-downloaded-message')
}).then(_ => {
this.isChecking = false
this.emit('will-updated')
setImmediate(() => {
setTimeout(() => {
this.updater.quitAndInstall()
})
}, 200)
})
}
updateCancelled () {
this.isChecking = false
}
updateError (event, error) {
this.isChecking = false
this.emit('update-error', error)
const msg = error == null ? '未知错误' : (error.stack || error).toString()
this.updater.logger.warn(`Update Error: ${msg}`)
dialog.showErrorBox('错误: ', msg)
const msg = (error == null)
? this.i18n.t('app.update-error-message')
: (error.stack || error).toString()
this.updater.logger.warn(`[Motrix] update-error: ${msg}`)
dialog.showErrorBox('Error', msg)
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ require('electron-debug')({
})
// Install `vue-devtools`
require('electron').app.on('ready', () => {
require('electron').app.whenReady().then(() => {
let installExtension = require('electron-devtools-installer')
installExtension.default(installExtension.VUEJS_DEVTOOLS)
.then(() => {})
+11 -63
View File
@@ -1,8 +1,15 @@
import { app } from 'electron'
import is from 'electron-is'
import { initialize } from '@electron/remote/main'
import logger from './core/Logger'
import Application from './Application'
import Launcher from './Launcher'
/**
* initialize the main-process side of the remote module
*/
initialize()
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true'
if (process.env.NODE_ENV !== 'development') {
global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
@@ -12,67 +19,8 @@ if (process.env.NODE_ENV !== 'development') {
* Fix Windows notification func
* appId defined in .electron-vue/webpack.main.config.js
*/
if (process.platform === 'win32') {
if (is.windows()) {
app.setAppUserModelId(appId)
}
function _init () {
let openURL = null
if (!is.mas()) {
app.on('open-url', (event, url) => {
logger.info(`You arrived from: ${url}`)
event.preventDefault()
openURL = url
if (global.application) {
global.application.handleProtocol(openURL)
}
})
}
app.on('ready', () => {
global.application = new Application()
global.application.start('index')
if (openURL) {
global.application.handleProtocol(openURL)
}
})
app.on('will-quit', () => {
logger.warn('will-quit')
global.application && global.application.stop()
})
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it's common NOT to close app even if all windows are closed
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
global.application.showPage('index')
})
}
function init () {
// Mac App Store Sandboxed App Not support requestSingleInstanceLock
if (is.mas()) {
_init()
} else {
const gotSingleLock = app.requestSingleInstanceLock()
if (!gotSingleLock) {
app.quit()
} else {
app.on('second-instance', (event, commandLine, workingDirectory) => {
global.application.showPage('index')
})
_init()
}
}
}
init()
global.launcher = new Launcher()
+77
View File
@@ -0,0 +1,77 @@
{
"menu": [
{
"id": "menu.app",
"submenu": [
{ "id": "app.about", "command": "application:about", "command-before": "application:show?page=index" },
{ "type": "separator" },
{ "id": "app.preferences", "command": "application:preferences" },
{ "id": "app.check-for-updates", "command": "application:check-for-updates" },
{ "id": "app.hide", "role": "hide" },
{ "id": "app.hide-others", "role": "hideothers" },
{ "id": "app.unhide", "role": "unhide" },
{ "type": "separator" },
{ "id": "app.quit", "role": "quit" }
]
},
{
"id": "menu.task",
"submenu": [
{ "id": "task.new-task", "command": "application:new-task", "command-after": "application:show?page=index" },
{ "id": "task.new-bt-task", "command": "application:new-bt-task", "command-after": "application:show?page=index" },
{ "id": "task.open-file", "command": "application:open-file", "command-before": "application:show?page=index" },
{ "type": "separator" },
{ "id": "task.pause-task", "command": "application:pause-task" },
{ "id": "task.resume-task", "command": "application:resume-task" },
{ "id": "task.delete-task", "command": "application:delete-task" },
{ "id": "task.move-task-up", "command": "application:move-task-up" },
{ "id": "task.move-task-down", "command": "application:move-task-down" },
{ "type": "separator" },
{ "id": "task.pause-all-task", "command": "application:pause-all-task" },
{ "id": "task.resume-all-task", "command": "application:resume-all-task" },
{ "id": "task.select-all-task", "command": "application:select-all-task" },
{ "type": "separator" },
{ "id": "task.clear-recent-tasks", "command": "application:clear-recent-tasks" }
]
},
{
"id": "menu.edit",
"submenu": [
{ "id": "edit.undo", "role": "undo" },
{ "id": "edit.redo", "role": "redo" },
{ "type": "separator" },
{ "id": "edit.cut", "role": "cut" },
{ "id": "edit.copy", "role": "copy" },
{ "id": "edit.paste", "role": "paste" },
{ "id": "edit.delete", "role": "delete" },
{ "id": "edit.select-all", "role": "selectall" }
]
},
{
"role": "window",
"id": "menu.window",
"submenu": [
{ "id": "window.reload", "role": "reload" },
{ "id": "window.close", "role": "close" },
{ "id": "window.minimize", "role": "minimize" },
{ "id": "window.zoom", "role": "zoom" },
{ "id": "window.toggle-fullscreen", "role": "togglefullscreen" },
{ "type": "separator" },
{ "id": "window.front", "role": "front" }
]
},
{
"role": "help",
"id": "menu.help",
"submenu": [
{ "id": "help.official-website", "command": "help:official-website" },
{ "id": "help.manual", "command": "help:manual" },
{ "id": "help.release-notes", "command": "help:release-notes" },
{ "type": "separator" },
{ "id": "help.report-problem", "command": "help:report-problem" },
{ "type": "separator" },
{ "id": "help.toggle-dev-tools", "role": "toggledevtools" }
]
}
]
}
-80
View File
@@ -1,80 +0,0 @@
{
"menu": [
{
"label": "Motrix",
"id": "menu.app",
"submenu": [
{ "label": "About Motrix", "id": "app.about", "command": "application:about", "command-before": "application:show,index"},
{ "type": "separator" },
{ "label": "Preferences...", "id": "app.preferences", "command": "application:preferences", "command-before": "application:show,index"},
{ "label": "Check for Updates...", "id": "app.check-for-updates", "command": "application:check-for-updates" },
{ "label": "Hide Motrix", "id": "app.hide", "role": "hide" },
{ "label": "Hide Others", "id": "app.hide-others", "role": "hideothers" },
{ "label": "Show All", "id": "app.unhide", "role": "unhide" },
{ "type": "separator" },
{ "label": "Quit Motrix", "id": "app.quit", "role": "quit" }
]
},
{
"label": "Task",
"id": "menu.task",
"submenu": [
{ "label": "New Task", "id": "task.new-task", "command": "application:new-task", "command-arg": "uri", "command-after": "application:show,index"},
{ "label": "New BT Task", "id": "task.new-bt-task", "command": "application:new-bt-task", "command-arg": "torrent", "command-after": "application:show,index"},
{ "type": "separator" },
{ "label": "Pause Task", "id": "task.pause-task", "command": "application:pause-task" },
{ "label": "Resume Task", "id": "task.resume-task", "command": "application:resume-task" },
{ "label": "Delete Task", "id": "task.delete-task", "command": "application:delete-task" },
{ "label": "Move Task Up", "id": "task.move-task-up", "command": "application:move-task-up" },
{ "label": "Move Task Down", "id": "task.move-task-down", "command": "application:move-task-down" },
{ "type": "separator" },
{ "label": "Pause All Task", "id": "task.pause-all-task", "command": "application:pause-all-task" },
{ "label": "Resume All Task", "id": "task.resume-all-task", "command": "application:resume-all-task" },
{ "type": "separator" },
{ "label": "Clear Recent Tasks", "id": "task.clear-recent-tasks", "command": "application:clear-recent-tasks" }
]
},
{
"label": "Edit",
"id": "menu.edit",
"submenu": [
{ "label": "Undo", "id": "edit.undo", "role": "undo" },
{ "label": "Redo", "id": "edit.redo", "role": "redo" },
{ "type": "separator" },
{ "label": "Cut", "id": "edit.cut", "role": "cut" },
{ "label": "Copy", "id": "edit.copy", "role": "copy" },
{ "label": "Paste", "id": "edit.paste", "role": "paste" },
{ "label": "Delete", "id": "edit.delete", "role": "delete" },
{ "label": "Select All", "id": "edit.select-all", "role": "selectall" }
]
},
{
"label": "Window",
"role": "window",
"id": "menu.window",
"submenu": [
{ "label": "Reload", "id": "window.reload", "role": "reload" },
{ "label": "Close", "id": "window.close", "role": "close" },
{ "label": "Minimize", "id": "window.minimize", "role": "minimize" },
{ "label": "Zoom", "id": "window.zoom", "role": "zoom" },
{ "label": "Enter Full Screen", "id": "window.toggle-fullscreen", "role": "togglefullscreen" },
{ "type": "separator" },
{ "label": "Bring All to Front", "id": "window.front", "role": "front" }
]
},
{
"label": "Help",
"role": "help",
"id": "menu.help",
"submenu": [
{ "label": "Motrix Website", "id": "help.official-website", "command": "help:official-website" },
{ "label": "Manual", "id": "help.manual", "command": "help:manual" },
{ "label": "Release Notes...", "id": "help.release-notes", "command": "help:release-notes" },
{ "type": "separator" },
{ "label": "Report Problem", "id": "help.report-problem", "command": "help:report-problem" },
{ "type": "separator" },
{ "label": "Toggle Developer Tools", "id": "help.toggle-dev-tools", "role": "toggledevtools" }
]
}
]
}
-80
View File
@@ -1,80 +0,0 @@
{
"menu": [
{
"label": "File",
"id": "menu.file",
"submenu": [
{ "label": "About Motrix", "id": "app.about", "command": "application:about", "command-before": "application:show,index"},
{ "type": "separator" },
{ "label": "Preferences...", "id": "app.preferences", "command": "application:preferences", "command-before": "application:show,index"},
{ "label": "Check for Updates...", "id": "app.check-for-updates", "command": "application:check-for-updates" },
{ "label": "Hide Motrix", "id": "app.hide", "role": "hide" },
{ "label": "Hide Others", "id": "app.hide-others", "role": "hideothers" },
{ "label": "Show All", "id": "app.unhide", "role": "unhide" },
{ "type": "separator" },
{ "label": "Quit Motrix", "id": "app.quit", "role": "quit" }
]
},
{
"label": "Task",
"id": "menu.task",
"submenu": [
{ "label": "New Task", "id": "task.new-task", "command": "application:new-task", "command-arg": "uri", "command-after": "application:show,index"},
{ "label": "New BT Task", "id": "task.new-bt-task", "command": "application:new-bt-task", "command-arg": "torrent", "command-after": "application:show,index"},
{ "type": "separator" },
{ "label": "Pause Task", "id": "task.pause-task", "command": "application:pause-task" },
{ "label": "Resume Task", "id": "task.resume-task", "command": "application:resume-task" },
{ "label": "Delete Task", "id": "task.delete-task", "command": "application:delete-task" },
{ "label": "Move Task Up", "id": "task.move-task-up", "command": "application:move-task-up" },
{ "label": "Move Task Down", "id": "task.move-task-down", "command": "application:move-task-down" },
{ "type": "separator" },
{ "label": "Pause All Task", "id": "task.pause-all-task", "command": "application:pause-all-task" },
{ "label": "Resume All Task", "id": "task.resume-all-task", "command": "application:resume-all-task" },
{ "type": "separator" },
{ "label": "Clear Recent Tasks", "id": "task.clear-recent-tasks", "command": "application:clear-recent-tasks" }
]
},
{
"label": "Edit",
"id": "menu.edit",
"submenu": [
{ "label": "Undo", "id": "edit.undo", "role": "undo" },
{ "label": "Redo", "id": "edit.redo", "role": "redo" },
{ "type": "separator" },
{ "label": "Cut", "id": "edit.cut", "role": "cut" },
{ "label": "Copy", "id": "edit.copy", "role": "copy" },
{ "label": "Paste", "id": "edit.paste", "role": "paste" },
{ "label": "Delete", "id": "edit.delete", "role": "delete" },
{ "label": "Select All", "id": "edit.select-all", "role": "selectall" }
]
},
{
"label": "Window",
"role": "window",
"id": "menu.window",
"submenu": [
{ "label": "Reload", "id": "window.reload", "role": "reload" },
{ "label": "Close", "id": "window.close", "role": "close" },
{ "label": "Minimize", "id": "window.minimize", "role": "minimize" },
{ "label": "Zoom", "id": "window.zoom", "role": "zoom" },
{ "label": "Enter Full Screen", "id": "window.toggle-fullscreen", "role": "togglefullscreen" },
{ "type": "separator" },
{ "label": "Bring All to Front", "id": "window.front", "role": "front" }
]
},
{
"label": "Help",
"role": "help",
"id": "menu.help",
"submenu": [
{ "label": "Motrix Website", "id": "help.official-website", "command": "help:official-website" },
{ "label": "Manual", "id": "help.manual", "command": "help:manual" },
{ "label": "Release Notes...", "id": "help.release-notes", "command": "help:release-notes" },
{ "type": "separator" },
{ "label": "Report Problem", "id": "help.report-problem", "command": "help:report-problem" },
{ "type": "separator" },
{ "label": "Toggle Developer Tools", "id": "help.toggle-dev-tools", "role": "toggledevtools" }
]
}
]
}
-80
View File
@@ -1,80 +0,0 @@
{
"menu": [
{
"label": "File",
"id": "menu.file",
"submenu": [
{ "label": "About Motrix", "id": "app.about", "command": "application:about", "command-before": "application:show,index"},
{ "type": "separator" },
{ "label": "Preferences...", "id": "app.preferences", "command": "application:preferences", "command-before": "application:show,index"},
{ "label": "Check for Updates...", "id": "app.check-for-updates", "command": "application:check-for-updates" },
{ "label": "Hide Motrix", "id": "app.hide", "role": "hide" },
{ "label": "Hide Others", "id": "app.hide-others", "role": "hideothers" },
{ "label": "Show All", "id": "app.unhide", "role": "unhide" },
{ "type": "separator" },
{ "label": "Quit Motrix", "id": "app.quit", "role": "quit" }
]
},
{
"label": "Task",
"id": "menu.task",
"submenu": [
{ "label": "New Task", "id": "task.new-task", "command": "application:new-task", "command-arg": "uri", "command-after": "application:show,index"},
{ "label": "New BT Task", "id": "task.new-bt-task", "command": "application:new-bt-task", "command-arg": "torrent", "command-after": "application:show,index"},
{ "type": "separator" },
{ "label": "Pause Task", "id": "task.pause-task", "command": "application:pause-task" },
{ "label": "Resume Task", "id": "task.resume-task", "command": "application:resume-task" },
{ "label": "Delete Task", "id": "task.delete-task", "command": "application:delete-task" },
{ "label": "Move Task Up", "id": "task.move-task-up", "command": "application:move-task-up" },
{ "label": "Move Task Down", "id": "task.move-task-down", "command": "application:move-task-down" },
{ "type": "separator" },
{ "label": "Pause All Task", "id": "task.pause-all-task", "command": "application:pause-all-task" },
{ "label": "Resume All Task", "id": "task.resume-all-task", "command": "application:resume-all-task" },
{ "type": "separator" },
{ "label": "Clear Recent Tasks", "id": "task.clear-recent-tasks", "command": "application:clear-recent-tasks" }
]
},
{
"label": "Edit",
"id": "menu.edit",
"submenu": [
{ "label": "Undo", "id": "edit.undo", "role": "undo" },
{ "label": "Redo", "id": "edit.redo", "role": "redo" },
{ "type": "separator" },
{ "label": "Cut", "id": "edit.cut", "role": "cut" },
{ "label": "Copy", "id": "edit.copy", "role": "copy" },
{ "label": "Paste", "id": "edit.paste", "role": "paste" },
{ "label": "Delete", "id": "edit.delete", "role": "delete" },
{ "label": "Select All", "id": "edit.select-all", "role": "selectall" }
]
},
{
"label": "Window",
"role": "window",
"id": "menu.window",
"submenu": [
{ "label": "Reload", "id": "window.reload", "role": "reload" },
{ "label": "Close", "id": "window.close", "role": "close" },
{ "label": "Minimize", "id": "window.minimize", "role": "minimize" },
{ "label": "Zoom", "id": "window.zoom", "role": "zoom" },
{ "label": "Enter Full Screen", "id": "window.toggle-fullscreen", "role": "togglefullscreen" },
{ "type": "separator" },
{ "label": "Bring All to Front", "id": "window.front", "role": "front" }
]
},
{
"label": "Help",
"role": "help",
"id": "menu.help",
"submenu": [
{ "label": "Motrix Website", "id": "help.official-website", "command": "help:official-website" },
{ "label": "Manual", "id": "help.manual", "command": "help:manual" },
{ "label": "Release Notes...", "id": "help.release-notes", "command": "help:release-notes" },
{ "type": "separator" },
{ "label": "Report Problem", "id": "help.report-problem", "command": "help:report-problem" },
{ "type": "separator" },
{ "label": "Toggle Developer Tools", "id": "help.toggle-dev-tools", "role": "toggledevtools" }
]
}
]
}
+73
View File
@@ -0,0 +1,73 @@
{
"menu": [
{
"id": "menu.file",
"submenu": [
{ "id": "app.about", "command": "application:about", "command-before": "application:show?page=index" },
{ "type": "separator" },
{ "id": "app.preferences", "command": "application:preferences" },
{ "id": "app.check-for-updates", "command": "application:check-for-updates" },
{ "id": "app.show", "command": "application:show", "command-arg": { "page": "index" } },
{ "type": "separator" },
{ "id": "app.quit", "role": "quit" }
]
},
{
"id": "menu.task",
"submenu": [
{ "id": "task.new-task", "command": "application:new-task", "command-after": "application:show?page=index" },
{ "id": "task.new-bt-task", "command": "application:new-bt-task", "command-after": "application:show?page=index" },
{ "id": "task.open-file", "command": "application:open-file", "command-before": "application:show?page=index" },
{ "type": "separator" },
{ "id": "task.pause-task", "command": "application:pause-task" },
{ "id": "task.resume-task", "command": "application:resume-task" },
{ "id": "task.delete-task", "command": "application:delete-task" },
{ "id": "task.move-task-up", "command": "application:move-task-up" },
{ "id": "task.move-task-down", "command": "application:move-task-down" },
{ "type": "separator" },
{ "id": "task.pause-all-task", "command": "application:pause-all-task" },
{ "id": "task.resume-all-task", "command": "application:resume-all-task" },
{ "id": "task.select-all-task", "command": "application:select-all-task" }
]
},
{
"id": "menu.edit",
"submenu": [
{ "id": "edit.undo", "role": "undo" },
{ "id": "edit.redo", "role": "redo" },
{ "type": "separator" },
{ "id": "edit.cut", "role": "cut" },
{ "id": "edit.copy", "role": "copy" },
{ "id": "edit.paste", "role": "paste" },
{ "id": "edit.delete", "role": "delete" },
{ "id": "edit.select-all", "role": "selectall" }
]
},
{
"role": "window",
"id": "menu.window",
"submenu": [
{ "id": "window.reload", "role": "reload" },
{ "id": "window.close", "role": "close" },
{ "id": "window.minimize", "role": "minimize" },
{ "id": "window.zoom", "role": "zoom" },
{ "id": "window.toggle-fullscreen", "role": "togglefullscreen" },
{ "type": "separator" },
{ "id": "window.front", "role": "front" }
]
},
{
"role": "help",
"id": "menu.help",
"submenu": [
{ "id": "help.official-website", "command": "help:official-website" },
{ "id": "help.manual", "command": "help:manual" },
{ "id": "help.release-notes", "command": "help:release-notes" },
{ "type": "separator" },
{ "id": "help.report-problem", "command": "help:report-problem" },
{ "type": "separator" },
{ "id": "help.toggle-dev-tools", "role": "toggledevtools" }
]
}
]
}
+5 -5
View File
@@ -1,6 +1,6 @@
[
{
"type": "button", "icon": "new-task", "id": "task.new-task", "command": "application:new-task", "command-arg": "uri", "command-after": "application:show,index"
"type": "button", "icon": "new-task", "id": "task.new-task", "command": "application:new-task", "command-after": "application:show?page=index"
},
{
"type": "spacer", "size": "small"
@@ -10,13 +10,13 @@
"id": "task.task-list",
"items": [
{
"type": "button", "icon": "task-active", "command": "application:task-list", "command-arg": "active"
"type": "button", "icon": "task-active", "command": "application:task-list", "command-arg": { "status": "active" }
},
{
"type": "button", "icon": "task-waiting", "command": "application:task-list", "command-arg": "waiting"
"type": "button", "icon": "task-waiting", "command": "application:task-list", "command-arg": { "status": "waiting" }
},
{
"type": "button", "icon": "task-stopped", "command": "application:task-list", "command-arg": "stopped"
"type": "button", "icon": "task-stopped", "command": "application:task-list", "command-arg": { "status": "stopped" }
}
]
},
@@ -30,6 +30,6 @@
"type": "spacer", "size": "small"
},
{
"type": "button", "icon": "about", "id": "app.about", "command": "application:about", "command-before": "application:show,index"
"type": "button", "icon": "about", "id": "app.about", "command": "application:about", "command-before": "application:show?page=index"
}
]
+12
View File
@@ -0,0 +1,12 @@
[
{ "id": "task.new-task", "command": "application:new-task", "command-after": "application:show?page=index" },
{ "id": "task.new-bt-task", "command": "application:new-bt-task", "command-arg": { "type": "torrent" }, "command-after": "application:show?page=index" },
{ "id": "task.open-file", "command": "application:open-file", "command-before": "application:show?page=index" },
{ "type": "separator" },
{ "id": "app.show", "command": "application:show", "command-arg": { "page": "index" } },
{ "id": "help.manual", "command": "help:manual" },
{ "id": "app.check-for-updates", "command": "application:check-for-updates" },
{ "type": "separator" },
{ "id": "app.preferences", "command": "application:preferences", "command-before": "application:show?page=index" },
{ "id": "app.quit", "command": "application:quit" }
]
+75
View File
@@ -0,0 +1,75 @@
{
"menu": [
{
"id": "menu.file",
"submenu": [
{ "id": "app.about", "command": "application:about", "command-before": "application:show?page=index" },
{ "type": "separator" },
{ "id": "app.preferences", "command": "application:preferences" },
{ "id": "app.check-for-updates", "command": "application:check-for-updates" },
{ "id": "app.show", "command": "application:show", "command-arg": { "page": "index" } },
{ "type": "separator" },
{ "id": "app.quit", "role": "quit" }
]
},
{
"id": "menu.task",
"submenu": [
{ "id": "task.new-task", "command": "application:new-task", "command-after": "application:show?page=index" },
{ "id": "task.new-bt-task", "command": "application:new-bt-task", "command-after": "application:show?page=index" },
{ "id": "task.open-file", "command": "application:open-file", "command-before": "application:show?page=index" },
{ "type": "separator" },
{ "id": "task.pause-task", "command": "application:pause-task" },
{ "id": "task.resume-task", "command": "application:resume-task" },
{ "id": "task.delete-task", "command": "application:delete-task" },
{ "id": "task.move-task-up", "command": "application:move-task-up" },
{ "id": "task.move-task-down", "command": "application:move-task-down" },
{ "type": "separator" },
{ "id": "task.pause-all-task", "command": "application:pause-all-task" },
{ "id": "task.resume-all-task", "command": "application:resume-all-task" },
{ "id": "task.select-all-task", "command": "application:select-all-task" },
{ "type": "separator" },
{ "id": "task.clear-recent-tasks", "command": "application:clear-recent-tasks" }
]
},
{
"id": "menu.edit",
"submenu": [
{ "id": "edit.undo", "role": "undo" },
{ "id": "edit.redo", "role": "redo" },
{ "type": "separator" },
{ "id": "edit.cut", "role": "cut" },
{ "id": "edit.copy", "role": "copy" },
{ "id": "edit.paste", "role": "paste" },
{ "id": "edit.delete", "role": "delete" },
{ "id": "edit.select-all", "role": "selectall" }
]
},
{
"role": "window",
"id": "menu.window",
"submenu": [
{ "id": "window.reload", "role": "reload" },
{ "id": "window.close", "role": "close" },
{ "id": "window.minimize", "role": "minimize" },
{ "id": "window.zoom", "role": "zoom" },
{ "id": "window.toggle-fullscreen", "role": "togglefullscreen" },
{ "type": "separator" },
{ "id": "window.front", "role": "front" }
]
},
{
"role": "help",
"id": "menu.help",
"submenu": [
{ "id": "help.official-website", "command": "help:official-website" },
{ "id": "help.manual", "command": "help:manual" },
{ "id": "help.release-notes", "command": "help:release-notes" },
{ "type": "separator" },
{ "id": "help.report-problem", "command": "help:report-problem" },
{ "type": "separator" },
{ "id": "help.toggle-dev-tools", "role": "toggledevtools" }
]
}
]
}
-80
View File
@@ -1,80 +0,0 @@
{
"menu": [
{
"label": "Motrix",
"id": "menu.app",
"submenu": [
{ "label": "关于 Motrix", "id": "app.about", "command": "application:about", "command-before": "application:show,index"},
{ "type": "separator" },
{ "label": "偏好设置...", "id": "app.preferences", "command": "application:preferences" },
{ "label": "检查更新...", "id": "app.check-for-updates", "command": "application:check-for-updates" },
{ "label": "隐藏 Motrix", "id": "app.hide", "role": "hide" },
{ "label": "隐藏其他", "id": "app.hide-others", "role": "hideothers" },
{ "label": "显示全部", "id": "app.unhide", "role": "unhide" },
{ "type": "separator" },
{ "label": "退出 Motrix", "id": "app.quit", "role": "quit" }
]
},
{
"label": "任务",
"id": "menu.task",
"submenu": [
{ "label": "新建任务", "id": "task.new-task", "command": "application:new-task", "command-after": "application:show,index"},
{ "label": "新建 BT 任务", "id": "task.new-bt-task", "command": "application:new-bt-task", "command-arg": "torrent", "command-after": "application:show,index"},
{ "type": "separator" },
{ "label": "暂停任务", "id": "task.pause-task", "command": "application:pause-task" },
{ "label": "恢复任务", "id": "task.resume-task", "command": "application:resume-task" },
{ "label": "删除任务", "id": "task.delete-task", "command": "application:delete-task" },
{ "label": "上移任务", "id": "task.move-task-up", "command": "application:move-task-up" },
{ "label": "下移任务", "id": "task.move-task-down", "command": "application:move-task-down" },
{ "type": "separator" },
{ "label": "暂停所有任务", "id": "task.pause-all-task", "command": "application:pause-all-task" },
{ "label": "恢复所有任务", "id": "task.resume-all-task", "command": "application:resume-all-task" },
{ "type": "separator" },
{ "label": "清除最近的下载记录", "id": "task.clear-recent-tasks", "command": "application:clear-recent-tasks" }
]
},
{
"label": "编辑",
"id": "menu.edit",
"submenu": [
{ "label": "撤销", "id": "edit.undo", "role": "undo" },
{ "label": "重做", "id": "edit.redo", "role": "redo" },
{ "type": "separator" },
{ "label": "剪切", "id": "edit.cut", "role": "cut" },
{ "label": "复制", "id": "edit.copy", "role": "copy" },
{ "label": "黏贴", "id": "edit.paste", "role": "paste" },
{ "label": "删除", "id": "edit.delete", "role": "delete" },
{ "label": "全选", "id": "edit.select-all", "role": "selectall" }
]
},
{
"label": "窗口",
"role": "window",
"id": "menu.window",
"submenu": [
{ "label": "重新加载", "id": "window.reload", "role": "reload" },
{ "label": "关闭", "id": "window.close", "role": "close" },
{ "label": "最小化", "id": "window.minimize", "role": "minimize" },
{ "label": "放大", "id": "window.zoom", "role": "zoom" },
{ "label": "进入全屏幕", "id": "window.toggle-fullscreen", "role": "togglefullscreen" },
{ "type": "separator" },
{ "label": "前置全部窗口", "id": "window.front", "role": "front" }
]
},
{
"label": "帮助",
"role": "help",
"id": "menu.help",
"submenu": [
{ "label": "Motrix 官网", "id": "help.official-website", "command": "help:official-website" },
{ "label": "使用手册", "id": "help.manual", "command": "help:manual" },
{ "label": "发行说明...", "id": "help.release-notes", "command": "help:release-notes" },
{ "type": "separator" },
{ "label": "报告问题", "id": "help.report-problem", "command": "help:report-problem" },
{ "type": "separator" },
{ "label": "开发者工具", "id": "help.toggle-dev-tools", "role": "toggledevtools" }
]
}
]
}
-80
View File
@@ -1,80 +0,0 @@
{
"menu": [
{
"label": "文件",
"id": "menu.file",
"submenu": [
{ "label": "关于 Motrix", "id": "app.about", "command": "application:about", "command-before": "application:show,index"},
{ "type": "separator" },
{ "label": "偏好设置...", "id": "app.preferences", "command": "application:preferences" },
{ "label": "检查更新...", "id": "app.check-for-updates", "command": "application:check-for-updates" },
{ "label": "隐藏 Motrix", "id": "app.hide", "role": "hide" },
{ "label": "隐藏其他", "id": "app.hide-others", "role": "hideothers" },
{ "label": "显示全部", "id": "app.unhide", "role": "unhide" },
{ "type": "separator" },
{ "label": "退出 Motrix", "id": "app.quit", "role": "quit" }
]
},
{
"label": "任务",
"id": "menu.task",
"submenu": [
{ "label": "新建任务", "id": "task.new-task", "command": "application:new-task", "command-after": "application:show,index"},
{ "label": "新建 BT 任务", "id": "task.new-bt-task", "command": "application:new-bt-task", "command-arg": "torrent", "command-after": "application:show,index"},
{ "type": "separator" },
{ "label": "暂停任务", "id": "task.pause-task", "command": "application:pause-task" },
{ "label": "恢复任务", "id": "task.resume-task", "command": "application:resume-task" },
{ "label": "删除任务", "id": "task.delete-task", "command": "application:delete-task" },
{ "label": "上移任务", "id": "task.move-task-up", "command": "application:move-task-up" },
{ "label": "下移任务", "id": "task.move-task-down", "command": "application:move-task-down" },
{ "type": "separator" },
{ "label": "暂停所有任务", "id": "task.pause-all-task", "command": "application:pause-all-task" },
{ "label": "恢复所有任务", "id": "task.resume-all-task", "command": "application:resume-all-task" },
{ "type": "separator" },
{ "label": "清除最近的下载记录", "id": "task.clear-recent-tasks", "command": "application:clear-recent-tasks" }
]
},
{
"label": "编辑",
"id": "menu.edit",
"submenu": [
{ "label": "撤销", "id": "edit.undo", "role": "undo" },
{ "label": "重做", "id": "edit.redo", "role": "redo" },
{ "type": "separator" },
{ "label": "剪切", "id": "edit.cut", "role": "cut" },
{ "label": "复制", "id": "edit.copy", "role": "copy" },
{ "label": "黏贴", "id": "edit.paste", "role": "paste" },
{ "label": "删除", "id": "edit.delete", "role": "delete" },
{ "label": "全选", "id": "edit.select-all", "role": "selectall" }
]
},
{
"label": "窗口",
"role": "window",
"id": "menu.window",
"submenu": [
{ "label": "重新加载", "id": "window.reload", "role": "reload" },
{ "label": "关闭", "id": "window.close", "role": "close" },
{ "label": "最小化", "id": "window.minimize", "role": "minimize" },
{ "label": "放大", "id": "window.zoom", "role": "zoom" },
{ "label": "进入全屏幕", "id": "window.toggle-fullscreen", "role": "togglefullscreen" },
{ "type": "separator" },
{ "label": "前置全部窗口", "id": "window.front", "role": "front" }
]
},
{
"label": "帮助",
"role": "help",
"id": "menu.help",
"submenu": [
{ "label": "Motrix 官网", "id": "help.official-website", "command": "help:official-website" },
{ "label": "使用手册", "id": "help.manual", "command": "help:manual" },
{ "label": "发行说明...", "id": "help.release-notes", "command": "help:release-notes" },
{ "type": "separator" },
{ "label": "报告问题", "id": "help.report-problem", "command": "help:report-problem" },
{ "type": "separator" },
{ "label": "开发者工具", "id": "help.toggle-dev-tools", "role": "toggledevtools" }
]
}
]
}
-80
View File
@@ -1,80 +0,0 @@
{
"menu": [
{
"label": "文件",
"id": "menu.file",
"submenu": [
{ "label": "关于 Motrix", "id": "app.about", "command": "application:about", "command-before": "application:show,index"},
{ "type": "separator" },
{ "label": "偏好设置...", "id": "app.preferences", "command": "application:preferences" },
{ "label": "检查更新...", "id": "app.check-for-updates", "command": "application:check-for-updates" },
{ "label": "隐藏 Motrix", "id": "app.hide", "role": "hide" },
{ "label": "隐藏其他", "id": "app.hide-others", "role": "hideothers" },
{ "label": "显示全部", "id": "app.unhide", "role": "unhide" },
{ "type": "separator" },
{ "label": "退出 Motrix", "id": "app.quit", "role": "quit" }
]
},
{
"label": "任务",
"id": "menu.task",
"submenu": [
{ "label": "新建任务", "id": "task.new-task", "command": "application:new-task", "command-after": "application:show,index"},
{ "label": "新建 BT 任务", "id": "task.new-bt-task", "command": "application:new-bt-task", "command-arg": "torrent", "command-after": "application:show,index"},
{ "type": "separator" },
{ "label": "暂停任务", "id": "task.pause-task", "command": "application:pause-task" },
{ "label": "恢复任务", "id": "task.resume-task", "command": "application:resume-task" },
{ "label": "删除任务", "id": "task.delete-task", "command": "application:delete-task" },
{ "label": "上移任务", "id": "task.move-task-up", "command": "application:move-task-up" },
{ "label": "下移任务", "id": "task.move-task-down", "command": "application:move-task-down" },
{ "type": "separator" },
{ "label": "暂停所有任务", "id": "task.pause-all-task", "command": "application:pause-all-task" },
{ "label": "恢复所有任务", "id": "task.resume-all-task", "command": "application:resume-all-task" },
{ "type": "separator" },
{ "label": "清除最近的下载记录", "id": "task.clear-recent-tasks", "command": "application:clear-recent-tasks" }
]
},
{
"label": "编辑",
"id": "menu.edit",
"submenu": [
{ "label": "撤销", "id": "edit.undo", "role": "undo" },
{ "label": "重做", "id": "edit.redo", "role": "redo" },
{ "type": "separator" },
{ "label": "剪切", "id": "edit.cut", "role": "cut" },
{ "label": "复制", "id": "edit.copy", "role": "copy" },
{ "label": "黏贴", "id": "edit.paste", "role": "paste" },
{ "label": "删除", "id": "edit.delete", "role": "delete" },
{ "label": "全选", "id": "edit.select-all", "role": "selectall" }
]
},
{
"label": "窗口",
"role": "window",
"id": "menu.window",
"submenu": [
{ "label": "重新加载", "id": "window.reload", "role": "reload" },
{ "label": "关闭", "id": "window.close", "role": "close" },
{ "label": "最小化", "id": "window.minimize", "role": "minimize" },
{ "label": "放大", "id": "window.zoom", "role": "zoom" },
{ "label": "进入全屏幕", "id": "window.toggle-fullscreen", "role": "togglefullscreen" },
{ "type": "separator" },
{ "label": "前置全部窗口", "id": "window.front", "role": "front" }
]
},
{
"label": "帮助",
"role": "help",
"id": "menu.help",
"submenu": [
{ "label": "Motrix 官网", "id": "help.official-website", "command": "help:official-website" },
{ "label": "使用手册", "id": "help.manual", "command": "help:manual" },
{ "label": "发行说明...", "id": "help.release-notes", "command": "help:release-notes" },
{ "type": "separator" },
{ "label": "报告问题", "id": "help.report-problem", "command": "help:report-problem" },
{ "type": "separator" },
{ "label": "开发者工具", "id": "help.toggle-dev-tools", "role": "toggledevtools" }
]
}
]
}
+62
View File
@@ -0,0 +1,62 @@
import is from 'electron-is'
import { EventEmitter } from 'events'
import { app } from 'electron'
import { bytesToSize } from '@shared/utils'
import {
APP_RUN_MODE
} from '@shared/constants'
const isMac = is.macOS()
export default class DockManager extends EventEmitter {
constructor (options) {
super()
this.options = options
const { runMode } = this.options
if (runMode !== APP_RUN_MODE.STANDARD) {
this.hide()
}
}
show = isMac
? () => {
if (app.dock.isVisible()) {
return
}
return app.dock.show()
}
: () => {}
hide = isMac
? () => {
if (!app.dock.isVisible()) {
return
}
app.dock.hide()
}
: () => {}
setBadge = isMac
? (text) => {
app.dock.setBadge(text)
}
: (text) => {}
handleSpeedChange = isMac
? (speed) => {
const { downloadSpeed } = speed
const text = downloadSpeed > 0 ? `${bytesToSize(downloadSpeed)}/s` : ''
this.setBadge(text)
}
: (text) => {}
openDock = isMac
? (path) => {
app.dock.downloadFinished(path)
}
: (path) => {}
}
+24
View File
@@ -0,0 +1,24 @@
import resources from '@shared/locales/app'
import LocaleManager from '@shared/locales/LocaleManager'
const localeManager = new LocaleManager({
resources
})
export function getLocaleManager () {
return localeManager
}
export function setupLocaleManager (locale) {
localeManager.changeLanguageByLocale(locale)
return localeManager
}
export function getI18n () {
return localeManager.getI18n()
}
export function getI18nTranslator () {
return localeManager.getI18n().t
}
+27 -25
View File
@@ -1,55 +1,57 @@
import { EventEmitter } from 'events'
import { Menu } from 'electron'
import {
translateTemplate,
flattenMenuItems,
updateStates
} from '../utils/menu'
import keymap from '@shared/keymap'
import { getI18n } from '../ui/Locale'
export default class MenuManager extends EventEmitter {
constructor (options) {
super()
this.options = options
this.i18n = getI18n()
this.keymap = keymap
this.template = []
this.menu = null
this.items = {}
this.load()
this.setup()
}
load (locale = 'en-US') {
let template = null
try {
template = require(`../menus/${locale}/${process.platform}.json`)
if (!template) {
template = require(`../menus/en-US/${process.platform}.json`)
}
} catch (err) {
template = require(`../menus/en-US/${process.platform}.json`)
}
this.template = template['menu']
load () {
const template = require(`../menus/${process.platform}.json`)
this.template = template.menu
}
build () {
const keystrokesByCommand = {}
for (let item in this.keymap) {
for (const item in this.keymap) {
keystrokesByCommand[this.keymap[item]] = item
}
const tpl = translateTemplate(this.template, keystrokesByCommand)
this.menu = Menu.buildFromTemplate(tpl)
// Deepclone the menu template to refresh menu
const template = JSON.parse(JSON.stringify(this.template))
const tpl = translateTemplate(template, keystrokesByCommand, this.i18n)
const menu = Menu.buildFromTemplate(tpl)
return menu
}
setup (locale) {
this.load(locale)
this.build()
Menu.setApplicationMenu(this.menu)
this.items = flattenMenuItems(this.menu)
setup () {
const menu = this.build()
Menu.setApplicationMenu(menu)
this.items = flattenMenuItems(menu)
}
updateStates (visibleStates, enabledStates, checkedStates) {
handleLocaleChange (locale) {
this.setup()
}
updateMenuStates (visibleStates, enabledStates, checkedStates) {
updateStates(this.items, visibleStates, enabledStates, checkedStates)
}
@@ -57,13 +59,13 @@ export default class MenuManager extends EventEmitter {
const visibleStates = {
[id]: flag
}
this.updateStates(visibleStates, null, null)
this.updateMenuStates(visibleStates, null, null)
}
updateMenuItemEnabledState (id, flag) {
const enabledStates = {
[id]: flag
}
this.updateStates(null, enabledStates, null)
this.updateMenuStates(null, enabledStates, null)
}
}
+44
View File
@@ -0,0 +1,44 @@
import { EventEmitter } from 'events'
import { nativeTheme } from 'electron'
import is from 'electron-is'
import { APP_THEME } from '@shared/constants'
import logger from '../core/Logger'
import { getSystemTheme } from '../utils'
export default class ThemeManager extends EventEmitter {
constructor (options = {}) {
super()
this.options = options
this.init()
}
init () {
this.systemTheme = getSystemTheme()
this.handleEvents()
}
getSystemTheme () {
return this.systemTheme
}
handleEvents () {
if (!is.macOS()) {
return
}
nativeTheme.on('updated', () => {
const theme = getSystemTheme()
this.systemTheme = theme
logger.info('[Motrix] nativeTheme updated===>', theme)
this.emit('system-theme-change', theme)
})
}
updateSystemTheme (theme) {
theme = theme === APP_THEME.AUTO ? 'system' : theme
nativeTheme.themeSource = theme
}
}
+28 -25
View File
@@ -1,6 +1,7 @@
import { EventEmitter } from 'events'
import { join } from 'path'
import { TouchBar, nativeImage } from 'electron'
import { handleCommand } from '../utils/menu'
import logger from '../core/Logger'
@@ -15,7 +16,7 @@ export default class TouchBarManager extends EventEmitter {
}
load () {
this.template = require(`../menus/touchBar.json`)
this.template = require('../menus/touchBar.json')
}
getClickFn (item) {
@@ -41,30 +42,32 @@ export default class TouchBarManager extends EventEmitter {
const { label, backgroundColor, textColor, size } = options
switch (type) {
case 'button':
const icon = this.getIconImage(options.icon)
const click = this.getClickFn(options)
result = new TouchBarButton({
label,
backgroundColor,
icon,
click
case 'button':
result = new TouchBarButton({
label,
backgroundColor,
icon: this.getIconImage(options.icon),
click: this.getClickFn(options)
})
break
case 'label':
result = new TouchBarLabel({
label,
textColor
})
break
case 'spacer':
result = new TouchBarSpacer({ size })
break
case 'group':
result = new TouchBarGroup({
items: new TouchBar({
items: options.items
})
break
case 'label':
result = new TouchBarLabel({
label,
textColor
})
break
case 'spacer':
result = new TouchBarSpacer({ size })
break
case 'group':
result = new TouchBarGroup({ items: options.items })
break
default:
result = null
})
break
default:
result = null
}
return result
@@ -90,7 +93,7 @@ export default class TouchBarManager extends EventEmitter {
if (!bar) {
try {
const items = this.build(this.template)
bar = new TouchBar(items)
bar = new TouchBar({ items })
this.bars[page] = bar
} catch (e) {
logger.info('getTouchBarByPage fail', e)
+355 -1
View File
@@ -1,3 +1,357 @@
export default class TrayManager {
import { EventEmitter } from 'events'
import { join } from 'path'
import { Tray, Menu, nativeImage } from 'electron'
import is from 'electron-is'
import { APP_THEME } from '@shared/constants'
import { getInverseTheme, getSystemMajorVersion } from '@shared/utils'
import { getI18n } from './Locale'
import {
translateTemplate,
flattenMenuItems,
updateStates
} from '../utils/menu'
import { convertArrayBufferToBuffer } from '../utils/index'
// import logger from '../core/Logger'
let tray = null
const { platform } = process
export default class TrayManager extends EventEmitter {
constructor (options = {}) {
super()
this.options = options
this.theme = options.theme || APP_THEME.AUTO
this.systemTheme = options.systemTheme
this.inverseSystemTheme = getInverseTheme(this.systemTheme)
this.bigSur = platform === 'darwin' && getSystemMajorVersion() >= 20
this.speedometer = options.speedometer
this.i18n = getI18n()
this.menu = null
this.cache = {}
this.uploadSpeed = 0
this.downloadSpeed = 0
this.status = false
this.focused = false
this.init()
}
init () {
this.loadTemplate()
this.loadImages()
this.initTray()
this.setupMenu()
this.handleEvents()
}
loadTemplate () {
this.template = require('../menus/tray.json')
}
loadImages () {
switch (platform) {
case 'darwin':
this.loadImagesForMacOS()
break
case 'win32':
this.loadImagesForWindows()
break
case 'linux':
this.loadImagesForLinux()
break
default:
this.loadImagesForDefault()
break
}
}
loadImagesForMacOS () {
if (this.bigSur) {
const {
systemTheme,
inverseSystemTheme
} = this
this.normalIcon = this.getFromCacheOrCreateImage(`mo-tray-${systemTheme}-normal.png`)
this.activeIcon = this.getFromCacheOrCreateImage(`mo-tray-${systemTheme}-active.png`)
// if (systemTheme === APP_THEME.DARK) {
// this.inverseNormalIcon = this.normalIcon
// this.inverseActiveIcon = this.activeIcon
// } else {
this.inverseNormalIcon = this.getFromCacheOrCreateImage(`mo-tray-${inverseSystemTheme}-normal.png`)
this.inverseActiveIcon = this.getFromCacheOrCreateImage(`mo-tray-${inverseSystemTheme}-active.png`)
// }
} else {
this.normalIcon = this.getFromCacheOrCreateImage('mo-tray-light-normal.png')
}
}
loadImagesForWindows () {
this.normalIcon = this.getFromCacheOrCreateImage('mo-tray-colorful-normal.png')
this.activeIcon = this.getFromCacheOrCreateImage('mo-tray-colorful-active.png')
}
loadImagesForLinux () {
const { theme } = this
if (theme === APP_THEME.AUTO) {
this.normalIcon = this.getFromCacheOrCreateImage('mo-tray-dark-normal.png')
this.activeIcon = this.getFromCacheOrCreateImage('mo-tray-dark-active.png')
} else {
this.normalIcon = this.getFromCacheOrCreateImage(`mo-tray-${theme}-normal.png`)
this.activeIcon = this.getFromCacheOrCreateImage(`mo-tray-${theme}-active.png`)
}
}
loadImagesForDefault () {
this.normalIcon = this.getFromCacheOrCreateImage('mo-tray-light-normal.png')
this.activeIcon = this.getFromCacheOrCreateImage('mo-tray-light-active.png')
}
getFromCacheOrCreateImage (key) {
let file = this.getCache(key)
if (file) {
return file
}
file = nativeImage.createFromPath(join(__static, `./${key}`))
file.setTemplateImage(this.bigSur)
this.setCache(key, file)
return file
}
getCache (key) {
return this.cache[key]
}
setCache (key, value) {
this.cache[key] = value
}
buildMenu () {
const keystrokesByCommand = {}
for (const item in this.keymap) {
keystrokesByCommand[this.keymap[item]] = item
}
// Deepclone the menu template to refresh menu
const template = JSON.parse(JSON.stringify(this.template))
const tpl = translateTemplate(template, keystrokesByCommand, this.i18n)
this.menu = Menu.buildFromTemplate(tpl)
this.items = flattenMenuItems(this.menu)
}
setupMenu () {
this.buildMenu()
this.updateContextMenu()
}
initTray () {
const { icon } = this.getIcons()
tray = new Tray(icon)
// tray.setPressedImage(inverseIcon)
tray.setToolTip('Motrix')
}
handleEvents () {
// All OS
tray.on('click', this.handleTrayClick)
// macOS, Windows
// tray.on('double-click', this.handleTrayDbClick)
tray.on('right-click', this.handleTrayRightClick)
tray.on('mouse-down', this.handleTrayMouseDown)
tray.on('mouse-up', this.handleTrayMouseUp)
// macOS only
tray.setIgnoreDoubleClickEvents(true)
tray.on('drop-files', this.handleTrayDropFiles)
tray.on('drop-text', this.handleTrayDropText)
}
handleTrayClick = (event) => {
global.application.toggle()
}
handleTrayDbClick = (event) => {
global.application.show()
}
handleTrayRightClick = (event) => {
tray.popUpContextMenu(this.menu)
}
handleTrayMouseDown = (event) => {
this.focused = true
this.emit('mouse-down', {
focused: true,
theme: this.inverseSystemTheme
})
this.renderTray()
}
handleTrayMouseUp = (event) => {
this.focused = false
this.emit('mouse-up', {
focused: false,
theme: this.theme
})
this.renderTray()
}
handleTrayDropFiles = (event, files) => {
this.emit('drop-files', files)
}
handleTrayDropText = (event, text) => {
this.emit('drop-text', text)
}
toggleSpeedometer (enabled) {
this.speedometer = enabled
}
async renderTray () {
if (this.speedometer) {
return
}
const { icon } = this.getIcons()
tray.setImage(icon)
// tray.setPressedImage(inverseIcon)
this.updateContextMenu()
}
getIcons () {
if (this.bigSur) {
return { icon: this.normalIcon }
}
const { focused, status, systemTheme } = this
const icon = status ? this.activeIcon : this.normalIcon
if (systemTheme === APP_THEME.DARK) {
return {
icon
}
}
const inverseIcon = status ? this.inverseActiveIcon : this.inverseNormalIcon
return {
icon: focused ? inverseIcon : icon
// inverseIcon: focused ? icon : inverseIcon
}
}
updateContextMenu () {
/**
* Linux requires setContextMenu to be called
* in order for the context menu to populate correctly
*/
if (process.platform !== 'linux') {
return
}
tray.setContextMenu(this.menu)
}
updateMenuStates (visibleStates, enabledStates, checkedStates) {
updateStates(this.items, visibleStates, enabledStates, checkedStates)
this.updateContextMenu()
}
updateMenuItemVisibleState (id, flag) {
const visibleStates = {
[id]: flag
}
this.updateMenuStates(visibleStates, null, null)
}
updateMenuItemEnabledState (id, flag) {
const enabledStates = {
[id]: flag
}
this.updateMenuStates(null, enabledStates, null)
}
handleLocaleChange (locale) {
this.setupMenu()
}
handleSpeedometerEnableChange (enabled) {
this.toggleSpeedometer(enabled)
this.renderTray()
}
handleSystemThemeChange (systemTheme = APP_THEME.LIGHT) {
if (!is.macOS()) {
return
}
this.systemTheme = systemTheme
this.inverseSystemTheme = getInverseTheme(systemTheme)
this.loadImages()
this.renderTray()
}
handleDownloadStatusChange (status) {
this.status = status
this.renderTray()
}
async handleSpeedChange ({ uploadSpeed, downloadSpeed }) {
if (!this.speedometer) {
return
}
this.uploadSpeed = uploadSpeed
this.downloadSpeed = downloadSpeed
await this.renderTray()
}
async updateTrayByImage (ab) {
const buffer = convertArrayBufferToBuffer(ab)
const image = nativeImage.createFromBuffer(buffer, {
scaleFactor: 2
})
image.setTemplateImage(this.bigSur)
tray.setImage(image)
}
destroy () {
if (tray) {
tray.removeListener('click', this.handleTrayClick)
// tray.removeListener('double-click', this.handleTrayDbClick)
tray.removeListener('right-click', this.handleTrayRightClick)
tray.removeListener('mouse-down', this.handleTrayMouseDown)
tray.removeListener('mouse-up', this.handleTrayMouseUp)
tray.removeListener('drop-files', this.handleTrayDropFiles)
tray.removeListener('drop-text', this.handleTrayDropText)
}
tray.destroy()
}
}
+163 -21
View File
@@ -1,13 +1,19 @@
import { join } from 'path'
import { EventEmitter } from 'events'
import { app, shell, BrowserWindow } from 'electron'
import { app, shell, screen, BrowserWindow } from 'electron'
import is from 'electron-is'
import pageConfig from '../configs/page'
import logger from '../core/Logger'
import { debounce } from 'lodash'
const defaultBrowserOptions = {
titleBarStyle: 'hiddenInset',
useContentSize: true,
show: false,
width: 1024,
height: 768
height: 768,
webPreferences: {
nodeIntegration: true
}
}
export default class WindowManager extends EventEmitter {
@@ -19,9 +25,9 @@ export default class WindowManager extends EventEmitter {
this.willQuit = false
app.on('before-quit', () => {
this.setWillQuit(true)
})
this.handleBeforeQuit()
this.handleAllWindowClosed()
}
setWillQuit (flag) {
@@ -32,46 +38,97 @@ export default class WindowManager extends EventEmitter {
const result = pageConfig[page] || {}
const hideAppMenu = this.userConfig['hide-app-menu']
if (hideAppMenu) {
result.frame = false
result.attrs.frame = false
}
// Optimized for small screen users
const { width, height } = screen.getPrimaryDisplay().workAreaSize
const widthScale = width >= 1280 ? 1 : 0.875
const heightScale = height >= 800 ? 1 : 0.875
result.attrs.width *= widthScale
result.attrs.height *= heightScale
// fix AppImage Dock Icon Missing
// https://github.com/AppImage/AppImageKit/wiki/Bundling-Electron-apps
if (is.linux()) {
result.attrs.icon = join(__static, './512x512.png')
}
return result
}
openWindow (page) {
const options = this.getPageOptions(page)
getPageBounds (page) {
const enabled = this.userConfig['keep-window-state']
const windowStateMap = this.userConfig['window-state'] || {}
let result = null
if (enabled) {
result = windowStateMap[page]
}
return result
}
openWindow (page, options = {}) {
const pageOptions = this.getPageOptions(page)
const { hidden } = options
const autoHideWindow = this.userConfig['auto-hide-window']
let window = this.windows[page] || null
if (window) {
window.restore()
window.show()
window.focus()
return window
}
window = new BrowserWindow({
...defaultBrowserOptions,
...options.attrs
...pageOptions.attrs,
webPreferences: {
enableRemoteModule: true,
contextIsolation: false,
nodeIntegration: true,
nodeIntegrationInWorker: true
},
hasShadow: !is.macOS()
})
const bounds = this.getPageBounds(page)
if (bounds) {
window.setBounds(bounds)
}
window.webContents.on('new-window', (e, url) => {
e.preventDefault()
shell.openExternal(url)
})
if (options.url) {
window.loadURL(options.url)
if (pageOptions.url) {
window.loadURL(pageOptions.url)
}
window.once('ready-to-show', () => {
window.show()
if (!hidden) {
window.show()
}
})
if (options.bindCloseToHide && process.platform === 'darwin') {
this.bindCloseToHide(page, window)
}
window.on('enter-full-screen', () => {
this.emit('enter-full-screen', window)
})
window.on('leave-full-screen', () => {
this.emit('leave-full-screen', window)
})
this.handleWindowState(page, window)
this.handleWindowClose(pageOptions, page, window)
this.bindAfterClosed(page, window)
this.addWindow(page, window)
if (autoHideWindow) {
this.handleWindowBlur()
}
return window
}
@@ -94,6 +151,9 @@ export default class WindowManager extends EventEmitter {
destroyWindow (page) {
const win = this.getWindow(page)
this.removeWindow(page)
win.removeListener('closed')
win.removeListener('move')
win.removeListener('resize')
win.destroy()
}
@@ -107,24 +167,106 @@ export default class WindowManager extends EventEmitter {
})
}
bindCloseToHide (page, window) {
handleWindowState (page, window) {
window.on('resize', debounce(() => {
const bounds = window.getBounds()
this.emit('window-resized', { page, bounds })
}, 500))
window.on('move', debounce(() => {
const bounds = window.getBounds()
this.emit('window-moved', { page, bounds })
}, 500))
}
handleWindowClose (pageOptions, page, window) {
window.on('close', (event) => {
if (!this.willQuit) {
if (pageOptions.bindCloseToHide && !this.willQuit) {
event.preventDefault()
window.hide()
// @see https://github.com/electron/electron/issues/20263
if (window.isFullScreen()) {
window.once('leave-full-screen', () => window.hide())
window.setFullScreen(false)
} else {
window.hide()
}
}
const bounds = window.getBounds()
this.emit('window-closed', { page, bounds })
})
}
showWindow (page) {
const window = this.getWindow(page)
if (!window || window.isVisible()) {
return
}
window.show()
}
hideWindow (page) {
const window = this.getWindow(page)
if (!window || !window.isVisible()) {
return
}
window.hide()
}
hideAllWindow () {
this.getWindowList().forEach((window) => {
window.hide()
})
}
toggleWindow (page) {
const window = this.getWindow(page)
if (!window) {
return
}
if (!window.isVisible() || window.isFullScreen()) {
window.show()
} else {
window.hide()
}
}
getFocusedWindow () {
return BrowserWindow.getFocusedWindow()
}
handleBeforeQuit () {
app.on('before-quit', () => {
this.setWillQuit(true)
})
}
onWindowBlur (event, window) {
window.hide()
}
handleWindowBlur () {
app.on('browser-window-blur', this.onWindowBlur)
}
unbindWindowBlur () {
app.removeListener('browser-window-blur', this.onWindowBlur)
}
handleAllWindowClosed () {
app.on('window-all-closed', (event) => {
event.preventDefault()
})
}
sendCommandTo (window, command, ...args) {
if (!window) {
return
}
console.log('sendCommandTo====>', window, command, ...args)
logger.info('[Motrix] send command to:', command, ...args)
window.webContents.send('command', command, ...args)
}
+102 -7
View File
@@ -1,17 +1,33 @@
import { app } from 'electron'
import { app, nativeTheme } from 'electron'
import is from 'electron-is'
import { resolve } from 'path'
import logger from '../core/Logger'
import { existsSync, lstatSync } from 'fs'
import {
APP_THEME,
ENGINE_MAX_CONNECTION_PER_SERVER,
IP_VERSION
} from '@shared/constants'
import engineBinMap from '../configs/engine'
export function getLogPath () {
return logger.transports.file.file
return app.getPath('logs')
}
export function getDhtPath (protocol) {
const name = protocol === IP_VERSION.V6 ? 'dht6.dat' : 'dht.dat'
return resolve(app.getPath('userData'), `./${name}`)
}
export function getSessionPath () {
return resolve(app.getPath('userData'), './download.session')
}
export function getEnginePidPath () {
return resolve(app.getPath('userData'), './engine.pid')
}
export function getUserDataPath () {
return app.getPath('userData')
}
@@ -21,12 +37,12 @@ export function getUserDownloadsPath () {
}
export function getEngineBin (platform) {
let result = engineBinMap.hasOwnProperty(platform) ? engineBinMap[platform] : ''
const result = engineBinMap[platform] || ''
return result
}
export function transformConfig (config) {
let result = []
const result = []
for (const [k, v] of Object.entries(config)) {
if (v !== '') {
result.push(`--${k}=${v}`)
@@ -44,17 +60,96 @@ export function isRunningInDmg () {
return result
}
export function moveAppToApplicationsFolder () {
export function moveAppToApplicationsFolder (errorMsg = '') {
return new Promise((resolve, reject) => {
try {
const result = app.moveToApplicationsFolder()
if (result) {
resolve(result)
} else {
reject(new Error('应用程序移动失败'))
reject(new Error(errorMsg))
}
} catch (err) {
reject(err)
}
})
}
export function splitArgv (argv) {
const args = []
const extra = {}
for (const arg of argv) {
if (arg.startsWith('--')) {
const kv = arg.split('=')
const key = kv[0]
const value = kv[1] || '1'
extra[key] = value
continue
}
args.push(arg)
}
return { args, extra }
}
export function parseArgvAsUrl (argv) {
const arg = argv[1]
if (!arg) {
return
}
if (checkIsSupportedSchema(arg)) {
return arg
}
}
export function checkIsSupportedSchema (url = '') {
const str = url.toLowerCase()
if (
str.startsWith('ftp:') ||
str.startsWith('http:') ||
str.startsWith('https:') ||
str.startsWith('magnet:') ||
str.startsWith('thunder:') ||
str.startsWith('mo:') ||
str.startsWith('motrix:')
) {
return true
} else {
return false
}
}
export function isDirectory (path) {
return existsSync(path) && lstatSync(path).isDirectory()
}
export function parseArgvAsFile (argv) {
let arg = argv[1]
if (!arg || isDirectory(arg)) {
return
}
if (is.linux()) {
arg = arg.replace('file://', '')
}
return arg
}
export const getMaxConnectionPerServer = () => {
return ENGINE_MAX_CONNECTION_PER_SERVER
}
export const getSystemTheme = () => {
let result = APP_THEME.LIGHT
result = nativeTheme.shouldUseDarkColors ? APP_THEME.DARK : APP_THEME.LIGHT
return result
}
export const convertArrayBufferToBuffer = (arrayBuffer) => {
const buffer = Buffer.alloc(arrayBuffer.byteLength)
const view = new Uint8Array(arrayBuffer)
for (let i = 0; i < buffer.length; ++i) {
buffer[i] = view[i]
}
return buffer
}
+62 -52
View File
@@ -1,33 +1,35 @@
import { parse } from 'querystring'
export function concat (template, submenu, submenuToAdd) {
submenuToAdd.forEach(sub => {
let relativeItem = null
if (sub.position) {
switch (sub.position) {
case 'first':
submenu.unshift(sub)
break
case 'last':
submenu.push(sub)
break
case 'before':
relativeItem = findById(template, sub['relative-id'])
if (relativeItem) {
let array = relativeItem.__parent
let index = array.indexOf(relativeItem)
array.splice(index, 0, sub)
}
break
case 'after':
relativeItem = findById(template, sub['relative-id'])
if (relativeItem) {
let array = relativeItem.__parent
let index = array.indexOf(relativeItem)
array.splice(index + 1, 0, sub)
}
break
default:
submenu.push(sub)
break
case 'first':
submenu.unshift(sub)
break
case 'last':
submenu.push(sub)
break
case 'before':
relativeItem = findById(template, sub['relative-id'])
if (relativeItem) {
const array = relativeItem.__parent
const index = array.indexOf(relativeItem)
array.splice(index, 0, sub)
}
break
case 'after':
relativeItem = findById(template, sub['relative-id'])
if (relativeItem) {
const array = relativeItem.__parent
const index = array.indexOf(relativeItem)
array.splice(index + 1, 0, sub)
}
break
default:
submenu.push(sub)
break
}
} else {
submenu.push(sub)
@@ -37,7 +39,7 @@ export function concat (template, submenu, submenuToAdd) {
export function merge (template, item) {
if (item.id) {
let matched = findById(template, item.id)
const matched = findById(template, item.id)
if (matched) {
if (item.submenu && Array.isArray(item.submenu)) {
if (!Array.isArray(matched.submenu)) {
@@ -54,15 +56,15 @@ export function merge (template, item) {
}
function findById (template, id) {
for (let i in template) {
let item = template[i]
for (const i in template) {
const item = template[i]
if (item.id === id) {
// Returned item need to have a reference to parent Array (.__parent).
// This is required to handle `position` and `relative-id`
item.__parent = template
return item
} else if (Array.isArray(item.submenu)) {
let result = findById(item.submenu, id)
const result = findById(item.submenu, id)
if (result) {
return result
}
@@ -71,19 +73,29 @@ function findById (template, id) {
return null
}
export function translateTemplate (template, keystrokesByCommand) {
for (let i in template) {
let item = template[i]
export function translateTemplate (template, keystrokesByCommand, i18n) {
for (const i in template) {
const item = template[i]
if (item.command) {
item.accelerator = acceleratorForCommand(item.command, keystrokesByCommand)
}
// If label is specified, label is used as the key of i18n.t(key),
// which mainly solves the inaccurate translation of item.id.
if (i18n) {
if (item.label) {
item.label = i18n.t(item.label)
} else if (item.id) {
item.label = i18n.t(item.id)
}
}
item.click = () => {
console.log('click sendCommand', item)
handleCommand(item)
}
if (item.submenu) {
translateTemplate(item.submenu, keystrokesByCommand)
translateTemplate(item.submenu, keystrokesByCommand, i18n)
}
}
return template
@@ -96,36 +108,34 @@ export function handleCommand (item) {
? [item.command, item['command-arg']]
: [item.command]
global.application.sendCommand(...args)
global.application.sendCommandToAll(...args)
handleCommandAfter(item)
}
function handleCommandBefore (item) {
console.log('handleCommandBefore==1=>', item)
if (!item['command-before']) {
return
}
const [ command, ...args ] = item['command-before'].split(',')
console.log('handleCommandBefore==2=>', command, ...args)
global.application.sendCommand(command, ...args)
const [command, params] = item['command-before'].split('?')
const args = parse(params)
global.application.sendCommandToAll(command, args)
}
function handleCommandAfter (item) {
console.log('handleCommandAfter==1=>', item)
if (!item['command-after']) {
return
}
const [ command, ...args ] = item['command-after'].split(',')
console.log('handleCommandAfter==2=>', command, ...args)
global.application.sendCommand(command, ...args)
const [command, params] = item['command-after'].split('?')
const args = parse(params)
global.application.sendCommandToAll(command, args)
}
function acceleratorForCommand (command, keystrokesByCommand) {
const keystroke = keystrokesByCommand[command]
if (keystroke) {
let modifiers = keystroke.split(/-(?=.)/)
let key = modifiers.pop().toUpperCase()
const key = modifiers.pop().toUpperCase()
.replace('+', 'Plus')
.replace('MINUS', '-')
modifiers = modifiers.map((modifier) => {
@@ -142,14 +152,14 @@ function acceleratorForCommand (command, keystrokesByCommand) {
.replace(/alt/ig, 'Alt')
}
})
let keys = modifiers.concat([key])
const keys = modifiers.concat([key])
return keys.join('+')
}
return null
}
export function flattenMenuItems (menu) {
let flattenItems = {}
const flattenItems = {}
menu.items.forEach(item => {
if (item.id) {
flattenItems[item.id] = item
@@ -163,24 +173,24 @@ export function flattenMenuItems (menu) {
export function updateStates (itemsById, visibleStates, enabledStates, checkedStates) {
if (visibleStates) {
for (let command in visibleStates) {
let item = itemsById[command]
for (const command in visibleStates) {
const item = itemsById[command]
if (item) {
item.visible = visibleStates[command]
}
}
}
if (enabledStates) {
for (let command in enabledStates) {
let item = itemsById[command]
for (const command in enabledStates) {
const item = itemsById[command]
if (item) {
item.enabled = enabledStates[command]
}
}
}
if (checkedStates) {
for (let id in checkedStates) {
let item = itemsById[id]
for (const id in checkedStates) {
const item = itemsById[id]
if (item) {
item.checked = checkedStates[id]
}
+165 -52
View File
@@ -1,28 +1,29 @@
import { remote } from 'electron'
import { ipcRenderer } from 'electron'
import is from 'electron-is'
import { isEmpty } from 'lodash'
import Aria2 from 'aria2'
import { isEmpty, clone } from 'lodash'
import { Aria2 } from '@shared/aria2'
import {
separateConfig,
compactUndefined,
formatOptionsForEngine,
mergeTaskResult,
changeKeysToCamelCase,
changeKeysToKebabCase
} from '@shared/utils'
const application = remote.getGlobal('application')
import { ENGINE_RPC_HOST } from '@shared/constants'
export default class Api {
constructor (options = {}) {
this.options = options
this.client = null
this.init()
}
init () {
this.loadConfig()
this.initClient()
async init () {
this.config = await this.loadConfig()
this.client = this.initClient()
this.client.open()
}
loadConfigFromLocalStorage () {
@@ -31,21 +32,18 @@ export default class Api {
return result
}
loadConfigFromNativeStore () {
const systemConfig = application.configManager.getSystemConfig()
const userConfig = application.configManager.getUserConfig()
const result = { ...systemConfig, ...userConfig }
async loadConfigFromNativeStore () {
const result = await ipcRenderer.invoke('get-app-config')
return result
}
loadConfig () {
async loadConfig () {
let result = is.renderer()
? this.loadConfigFromNativeStore()
? await this.loadConfigFromNativeStore()
: this.loadConfigFromLocalStorage()
result = changeKeysToCamelCase(result)
this.config = result
return result
}
initClient () {
@@ -53,11 +51,12 @@ export default class Api {
rpcListenPort: port,
rpcSecret: secret
} = this.config
this.client = new Aria2({
const host = ENGINE_RPC_HOST
return new Aria2({
host,
port,
secret
})
this.client.open()
}
closeClient () {
@@ -72,7 +71,7 @@ export default class Api {
fetchPreference () {
return new Promise((resolve) => {
this.loadConfig()
this.config = this.loadConfig()
resolve(this.config)
})
}
@@ -80,9 +79,9 @@ export default class Api {
savePreference (params = {}) {
const kebabParams = changeKeysToKebabCase(params)
if (is.renderer()) {
this.savePreferenceToNativeStore(kebabParams)
return this.savePreferenceToNativeStore(kebabParams)
} else {
this.savePreferenceToLocalStorage(kebabParams)
return this.savePreferenceToLocalStorage(kebabParams)
}
}
@@ -92,25 +91,78 @@ export default class Api {
savePreferenceToNativeStore (params = {}) {
const { user, system, others } = separateConfig(params)
if (!isEmpty(system)) {
console.info('[Motrix] save system config: ', system)
application.configManager.setSystemConfig(system)
}
const config = {}
if (!isEmpty(user)) {
console.info('[Motrix] save user config: ', user)
application.configManager.setUserConfig(user)
config.user = user
}
if (!isEmpty(system)) {
console.info('[Motrix] save system config: ', system)
config.system = system
this.updateActiveTaskOption(system)
}
if (!isEmpty(others)) {
console.info('[Motrix] save config found iillegal key: ', others)
console.info('[Motrix] save config found illegal key: ', others)
}
ipcRenderer.send('command', 'application:save-preference', config)
}
getVersion () {
return this.client.call('getVersion')
}
changeGlobalOption (options) {
const args = formatOptionsForEngine(options)
return this.client.call('changeGlobalOption', args)
}
getGlobalOption () {
return new Promise((resolve) => {
this.client.call('getGlobalOption')
.then((data) => {
resolve(changeKeysToCamelCase(data))
})
})
}
getOption (params = {}) {
const { gid } = params
const args = compactUndefined([gid])
return new Promise((resolve) => {
this.client.call('getOption', ...args)
.then((data) => {
resolve(changeKeysToCamelCase(data))
})
})
}
updateActiveTaskOption (options) {
this.fetchTaskList({ type: 'active' })
.then((data) => {
if (isEmpty(data)) {
return
}
const gids = data.map((task) => task.gid)
this.batchChangeOption({ gids, options })
})
}
changeOption (params = {}) {
const { gid, options = {} } = params
const engineOptions = formatOptionsForEngine(options)
const args = compactUndefined([gid, engineOptions])
return this.client.call('changeOption', ...args)
}
getGlobalStat () {
return this.client.call('getGlobalStat')
}
@@ -118,11 +170,16 @@ export default class Api {
addUri (params) {
const {
uris,
outs,
options
} = params
const tasks = uris.map((uri) => {
const args = compactUndefined([[uri], options])
return [ 'aria2.addUri', ...args ]
const tasks = uris.map((uri, index) => {
const engineOptions = formatOptionsForEngine(options)
if (outs && outs[index]) {
engineOptions.out = outs[index]
}
const args = compactUndefined([[uri], engineOptions])
return ['aria2.addUri', ...args]
})
return this.client.multicall(tasks)
}
@@ -132,7 +189,8 @@ export default class Api {
torrent,
options
} = params
const args = compactUndefined([torrent, [], options])
const engineOptions = formatOptionsForEngine(options)
const args = compactUndefined([torrent, [], engineOptions])
return this.client.call('addTorrent', ...args)
}
@@ -141,37 +199,38 @@ export default class Api {
metalink,
options
} = params
const args = compactUndefined([metalink, options])
const engineOptions = formatOptionsForEngine(options)
const args = compactUndefined([metalink, engineOptions])
return this.client.call('addMetalink', ...args)
}
fetchDownloadingTaskList (params = {}) {
const { offset = 0, num = 200, keys } = params
const { offset = 0, num = 20, keys } = params
const activeArgs = compactUndefined([keys])
const waitingArgs = compactUndefined([offset, num, keys])
return new Promise((resolve, reject) => {
this.client.multicall([
[ 'aria2.tellActive', ...activeArgs ],
[ 'aria2.tellWaiting', ...waitingArgs ]
['aria2.tellActive', ...activeArgs],
['aria2.tellWaiting', ...waitingArgs]
]).then((data) => {
console.log('fetchDownloadingTaskList data', data)
console.log('[Motrix] fetch downloading task list data:', data)
const result = mergeTaskResult(data)
resolve(result)
}).catch((err) => {
console.log('fetchDownloadingTaskList fail===>', err)
console.log('[Motrix] fetch downloading task list fail:', err)
reject(err)
})
})
}
fetchWaitingTaskList (params = {}) {
const { offset = 0, num = 200, keys } = params
const { offset = 0, num = 20, keys } = params
const args = compactUndefined([offset, num, keys])
return this.client.call('tellWaiting', ...args)
}
fetchStoppedTaskList (params = {}) {
const { offset = 0, num = 200, keys } = params
const { offset = 0, num = 20, keys } = params
const args = compactUndefined([offset, num, keys])
return this.client.call('tellStopped', ...args)
}
@@ -179,14 +238,14 @@ export default class Api {
fetchTaskList (params = {}) {
const { type } = params
switch (type) {
case 'active':
return this.fetchDownloadingTaskList(params)
case 'waiting':
return this.fetchWaitingTaskList(params)
case 'stopped':
return this.fetchStoppedTaskList(params)
default:
return this.fetchDownloadingTaskList(params)
case 'active':
return this.fetchDownloadingTaskList(params)
case 'waiting':
return this.fetchWaitingTaskList(params)
case 'stopped':
return this.fetchStoppedTaskList(params)
default:
return this.fetchDownloadingTaskList(params)
}
}
@@ -196,6 +255,36 @@ export default class Api {
return this.client.call('tellStatus', ...args)
}
fetchTaskItemWithPeers (params = {}) {
const { gid, keys } = params
const statusArgs = compactUndefined([gid, keys])
const peersArgs = compactUndefined([gid])
return new Promise((resolve, reject) => {
this.client.multicall([
['aria2.tellStatus', ...statusArgs],
['aria2.getPeers', ...peersArgs]
]).then((data) => {
console.log('[Motrix] fetchTaskItemWithPeers:', data)
const result = data[0] && data[0][0]
const peers = data[1] && data[1][0]
result.peers = peers || []
console.log('[Motrix] fetchTaskItemWithPeers.result:', result)
console.log('[Motrix] fetchTaskItemWithPeers.peers:', peers)
resolve(result)
}).catch((err) => {
console.log('[Motrix] fetch downloading task list fail:', err)
reject(err)
})
})
}
fetchTaskItemPeers (params = {}) {
const { gid, keys } = params
const args = compactUndefined([gid, keys])
return this.client.call('getPeers', ...args)
}
pauseTask (params = {}) {
const { gid } = params
const args = compactUndefined([gid])
@@ -252,11 +341,35 @@ export default class Api {
return this.client.call('removeDownloadResult', ...args)
}
startPowerSaveBlocker () {
application.energyManager.startPowerSaveBlocker()
multicall (method, params = {}) {
let { gids, options = {} } = params
options = formatOptionsForEngine(options)
const data = gids.map((gid, index) => {
const _options = clone(options)
const args = compactUndefined([gid, _options])
return [method, ...args]
})
return this.client.multicall(data)
}
stopPowerSaveBlocker () {
application.energyManager.stopPowerSaveBlocker()
batchChangeOption (params = {}) {
return this.multicall('aria2.changeOption', params)
}
batchRemoveTask (params = {}) {
return this.multicall('aria2.remove', params)
}
batchResumeTask (params = {}) {
return this.multicall('aria2.unpause', params)
}
batchPauseTask (params = {}) {
return this.multicall('aria2.pause', params)
}
batchForcePauseTask (params = {}) {
return this.multicall('aria2.forcePause', params)
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 10 KiB

+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<g class="nc-icon-wrapper" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentColor">
<line data-cap="butt" data-color="color-2" fill="none" stroke-miterlimit="10" x1="12" y1="2" x2="12" y2="22"/>
<polyline fill="none" stroke="currentColor" stroke-miterlimit="10" points="19,15 12,22 5,15 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 429 B

+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<g class="nc-icon-wrapper" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentColor">
<line data-cap="butt" data-color="color-2" fill="none" stroke-miterlimit="10" x1="12" y1="22" x2="12" y2="2"/>
<polyline fill="none" stroke="currentColor" stroke-miterlimit="10" points="5,9 12,2 19,9 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 426 B

+10
View File
@@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<g stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentColor">
<rect x="4" y="3" width="16" height="18" fill="none" stroke="currentColor" stroke-miterlimit="10"/>
<line data-color="color-2" x1="1" y1="6" x2="1" y2="18" fill="none" stroke-miterlimit="10"/>
<line data-color="color-2" x1="23" y1="6" x2="23" y2="18" fill="none" stroke-miterlimit="10"/>
<polyline data-cap="butt" points="10 15 10 8 16 8 16 14" fill="none" stroke="currentColor" stroke-miterlimit="10"/>
<circle data-stroke="none" cx="9" cy="15" r="2" stroke="none"/>
<circle data-stroke="none" cx="15" cy="14" r="2" stroke="none"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 747 B

+11
View File
@@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<g stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentColor">
<polyline data-cap="butt" fill="none" stroke="currentColor" stroke-miterlimit="10" points="17,23 17,7 1,7 "/>
<line data-cap="butt" fill="none" stroke="currentColor" stroke-miterlimit="10" x1="17" y1="7" x2="23" y2="1"/>
<polygon fill="none" stroke="currentColor" stroke-miterlimit="10" points="17,23 23,17 23,1 7,1 1,7 1,23 "/>
<circle data-color="color-2" data-stroke="none" cx="12" cy="12" r="1" stroke-linejoin="miter" stroke-linecap="square" stroke="none"/>
<circle data-color="color-2" data-stroke="none" cx="6" cy="12" r="1" stroke-linejoin="miter" stroke-linecap="square" stroke="none"/>
<circle data-color="color-2" data-stroke="none" cx="12" cy="18" r="1" stroke-linejoin="miter" stroke-linecap="square" stroke="none"/>
<circle data-color="color-2" data-stroke="none" cx="6" cy="18" r="1" stroke-linejoin="miter" stroke-linecap="square" stroke="none"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+7
View File
@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<g stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentColor">
<polyline data-cap="butt" data-color="color-2" points="1 20 6 14 10 18 17 10 23 17" fill="none" stroke-miterlimit="10"/>
<rect x="1" y="3" width="22" height="18" fill="none" stroke="currentColor" stroke-miterlimit="10"/>
<circle data-color="color-2" cx="9" cy="8" r="2" fill="none" stroke-miterlimit="10"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 509 B

+9
View File
@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<g stroke-linecap="square" stroke-linejoin="miter" stroke-width="2" fill="#000000" stroke="#000000">
<line fill="none" stroke-miterlimit="10" x1="8.2" y1="4.5" x2="11.1" y2="7.3"></line>
<line fill="none" stroke-miterlimit="10" x1="16.7" y1="12.9" x2="19.5" y2="15.8"></line>
<path fill="none" stroke="#000000" stroke-miterlimit="10"
d="M12.5,17.2 c-1.6,1.6-4.1,1.6-5.7,0c-1.6-1.6-1.6-4.1,0-5.7l7.1-7.1l-2.8-2.8L4,8.7C0.9,11.8,0.9,16.9,4,20s8.2,3.1,11.3,0l7.1-7.1l-2.8-2.8 L12.5,17.2z">
</path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 617 B

+9
View File
@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<g class="nc-icon-wrapper" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentColor">
<polyline data-cap="butt" fill="none" stroke-miterlimit="10" points="12,9 12,13 7.8,16.1 "/>
<line data-cap="butt" fill="none" stroke-miterlimit="10" x1="12" y1="13" x2="16.2" y2="16.1"/>
<circle fill="none" stroke="currentColor" stroke-miterlimit="10" cx="12" cy="5" r="4"/>
<circle fill="none" stroke="currentColor" stroke-miterlimit="10" cx="5" cy="19" r="4"/>
<circle fill="none" stroke="currentColor" stroke-miterlimit="10" cx="19" cy="19" r="4"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 687 B

+10
View File
@@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<g class="nc-icon-wrapper" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentColor">
<path fill="none" stroke="currentColor" stroke-miterlimit="10" d="M3,14V4 c0-0.552,0.448-1,1-1h16c0.552,0,1,0.448,1,1v6"/>
<path fill="none" stroke="currentColor" stroke-miterlimit="10" d="M10,18H1v0 c0,1.657,1.343,3,3,3h6"/>
<path data-cap="butt" data-color="color-2" fill="none" stroke-miterlimit="10" d="M14.126,17 c0.444-1.725,2.01-3,3.874-3c1.48,0,2.772,0.804,3.464,1.999"/>
<polygon data-color="color-2" data-stroke="none" points="23.22,13.649 22.792,18 18.522,17.061 " stroke-linejoin="miter" stroke-linecap="square" stroke="none"/>
<path data-cap="butt" data-color="color-2" fill="none" stroke-miterlimit="10" d="M21.874,20 c-0.444,1.725-2.01,3-3.874,3c-1.48,0-2.772-0.804-3.464-1.999"/>
<polygon data-color="color-2" data-stroke="none" points="12.78,23.351 13.208,19 17.478,19.939 " stroke-linejoin="miter" stroke-linecap="square" stroke="none"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<g>
<path d="M12,0C5.383,0,0,5.383,0,12s5.383,12,12,12s12-5.383,12-12S18.617,0,12,0z M19,13h-8V5h2v6h6V13z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 214 B

@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<g stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentColor">
<path data-cap="butt" fill="none" stroke="currentColor" stroke-miterlimit="10" d="M6.121,20.121 C7.727,21.22,9.907,22,12,22c5.523,0,10-4.477,10-10c0-5.523-4.477-10-10-10C8.101,2,4.728,4.233,3.078,7.488"/>
<polyline fill="none" stroke="currentColor" stroke-miterlimit="10" points="2.278,1.588 3.078,7.488 9.078,6.688 "/>
<circle data-color="color-2" fill="none" stroke-miterlimit="10" cx="4" cy="18" r="3"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 609 B

+12
View File
@@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<g stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentColor">
<line data-cap="butt" data-color="color-2" x1="2" y1="6" x2="22" y2="6" fill="none" stroke-miterlimit="10"/>
<line data-cap="butt" data-color="color-2" x1="12" y1="2" x2="12" y2="22" fill="none" stroke-miterlimit="10"/>
<line data-cap="butt" data-color="color-2" x1="7" y1="2" x2="7" y2="6" fill="none" stroke-miterlimit="10"/>
<line data-cap="butt" data-color="color-2" x1="17" y1="2" x2="17" y2="6" fill="none" stroke-miterlimit="10"/>
<line data-cap="butt" data-color="color-2" x1="2" y1="18" x2="22" y2="18" fill="none" stroke-miterlimit="10"/>
<line data-cap="butt" data-color="color-2" x1="7" y1="22" x2="7" y2="18" fill="none" stroke-miterlimit="10"/>
<line data-cap="butt" data-color="color-2" x1="17" y1="22" x2="17" y2="18" fill="none" stroke-miterlimit="10"/>
<rect x="2" y="2" width="20" height="20" fill="none" stroke="currentColor" stroke-miterlimit="10"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Some files were not shown because too many files have changed in this diff Show More