Compare commits
130 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 83b55b806d | |||
| d4dab6de9b | |||
| deae5e8e33 | |||
| b098c8c9bc | |||
| b12553cc45 | |||
| 8891b9a79c | |||
| a44f088139 | |||
| 7ea0cd3e75 | |||
| c93cc9d23b | |||
| 8d2e14486d | |||
| 3775da5e36 | |||
| 2e21285f99 | |||
| 6c2dde8e59 | |||
| e014580512 | |||
| e970a51b71 | |||
| 019f8be306 | |||
| 20f79dacb7 | |||
| 1bdd17a80a | |||
| b01e006073 | |||
| 82728a2b23 | |||
| 217d2df5be | |||
| 960f0674ef | |||
| 54e9f326d9 | |||
| 4e7267028f | |||
| efd7f97a36 | |||
| 5bb790822d | |||
| 71f3fb601b | |||
| af710aa265 | |||
| 52b6fb0849 | |||
| b8d63374b7 | |||
| ff38d4ea5c | |||
| a24a7acfaf | |||
| 16e9c8d848 | |||
| f36cdccf9f | |||
| c826a7dd77 | |||
| b96518a42c | |||
| 02f0b66500 | |||
| 377bc47d87 | |||
| f8a4ef267d | |||
| baea3f0345 | |||
| 1fcf0bb0d0 | |||
| 85e1acfe5b | |||
| 41ac6ad335 | |||
| b151c45e70 | |||
| b3686fff04 | |||
| af81107b3d | |||
| 88224998b7 | |||
| 8508ca9b3c | |||
| 6fad6a876c | |||
| 6c8a844cd9 | |||
| 4657a503f9 | |||
| 324347e591 | |||
| 16c376c108 | |||
| 79cad28cc1 | |||
| ac16bd91c2 | |||
| fafeaca47d | |||
| 3152252fb8 | |||
| a5240bfeb0 | |||
| 64cda63587 | |||
| fe071a3783 | |||
| 5d812e9c4e | |||
| f36ba605e2 | |||
| e7ed58e394 | |||
| be789e7ea8 | |||
| 780a01e404 | |||
| b45518a5b6 | |||
| 2401d68a24 | |||
| 6cb2986f39 | |||
| cb8e0dbd2e | |||
| b4faed0621 | |||
| 249aa616fe | |||
| 482ccb3293 | |||
| f1be6bc1a4 | |||
| 326e8c700b | |||
| 2a538fd7c3 | |||
| c424b981b3 | |||
| a284aba2cc | |||
| c8bfdbf087 | |||
| eb80f3698f | |||
| 23f3d85ad4 | |||
| 24019123ba | |||
| 06a471982a | |||
| 43627aba50 | |||
| 8116234b3e | |||
| e488de5c3f | |||
| 084f834a41 | |||
| 97d30ee85e | |||
| 387ccc9cf7 | |||
| fed5744607 | |||
| 3e2b448e09 | |||
| c12c13066d | |||
| 5c36454ca0 | |||
| 7b6ba13d94 | |||
| 5d93d4d7bb | |||
| 4d024eb6a6 | |||
| 182acec265 | |||
| e293b16343 | |||
| 70cf36d7b2 | |||
| f3d8cac9ba | |||
| 620b243794 | |||
| 37fe7d4dbd | |||
| 11b6d651b8 | |||
| 8a5bc11d88 | |||
| bf69146035 | |||
| 14ff0c4bbe | |||
| d9706a2c3e | |||
| c36f7b73f1 | |||
| 7e6d0542cc | |||
| 72bf4ec909 | |||
| fa87b8ff9b | |||
| 31203e72fc | |||
| 5bd9875f61 | |||
| 646ad28fbc | |||
| a66d482d3a | |||
| 5dfc8cce37 | |||
| 4c88431147 | |||
| bb06b3970d | |||
| c86767bc3f | |||
| 3c6d14ec7e | |||
| 88a9a69c27 | |||
| da7241cd6a | |||
| 397055826e | |||
| 2e6b8bb5fa | |||
| ed4f3afcbd | |||
| 53ab75fbf9 | |||
| c19cf17b07 | |||
| a994f45e8f | |||
| 1bdaeeb3a6 | |||
| 32f0a3d084 | |||
| ba4ef326f7 |
@@ -0,0 +1,8 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
@@ -143,20 +143,6 @@ let webConfig = {
|
||||
? 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
|
||||
// },
|
||||
nodeModules: devMode
|
||||
? path.resolve(__dirname, '../node_modules')
|
||||
: false
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.IS_WEB': 'true'
|
||||
}),
|
||||
|
||||
@@ -2,11 +2,16 @@
|
||||
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.**
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
@@ -23,12 +28,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.
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
name: 错误反馈
|
||||
about: 创建一个错误报告帮助改进「请按照模板提交,提供详细的信息,方便我们复现之后处理」
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
**反馈之前**
|
||||
反馈之前请搜索一下已有 issues 和 帮助文档,看是否有类似问题可以解决你的问题
|
||||
https://github.com/agalwood/Motrix/issues
|
||||
http://motrix.app/support
|
||||
|
||||
**请删除上面和本行的内容,然后按以下格式填写反馈信息,谢谢**
|
||||
|
||||
**错误描述**
|
||||
清楚简洁地描述错误,方便我们复现之后处理。
|
||||
|
||||
**如何重现**
|
||||
重现步骤,如:
|
||||
1. 点击新建任务按钮
|
||||
2. 黏贴链接(如链接不涉及到隐私和版权问题,请顺便提供)
|
||||
3. 点击提交
|
||||
4. 发现报错
|
||||
|
||||
**预期的行为**
|
||||
清楚简洁地描述您期望发生的事情。
|
||||
|
||||
**截图**
|
||||
请添加屏幕截图以帮助解释您的问题:
|
||||
打开应用菜单中的「帮助」——「开发者工具」—— 切换到 console,然后**完整**截图。
|
||||
|
||||
**运行环境**
|
||||
- 操作系统类型: [如 macOS, Windows, Linux]
|
||||
- 具体版本: [如 macOS 10.14.2, Windows 10, Ubuntu 18.04]
|
||||
- Motrix 版本: [如 v1.1.3, v1.1.0]
|
||||
- 安装包类型:[如 dmg, AppImage]
|
||||
|
||||
**更多信息**
|
||||
添加有关此问题的任何其他上下文信息。
|
||||
@@ -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: 30
|
||||
|
||||
# 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
|
||||
@@ -0,0 +1,37 @@
|
||||
# Motrix 贡献指南
|
||||
|
||||
## 🌍 翻译指南
|
||||
首先你要确定一个语言的英文简写作为 **locale**,如 en-US,这个 locale 值请严格参考 [Electron 的 Locales 文档](https://electronjs.org/docs/api/locales)
|
||||
|
||||
Motrix 的国际化分三部分:
|
||||
- Element UI
|
||||
- 应用菜单
|
||||
- 主界面
|
||||
|
||||
### Element UI
|
||||
Element UI 的国际化由 [Element 社区](http://element.eleme.io/#/en-US/component/i18n)提供,找到 **locale** 对应的语言包文件「两者 locale 命名可能不一致」,在 `src/shared/locales/all.js` 中引入,如
|
||||
```
|
||||
import eleLocaleEn from 'element-ui/lib/locale/lang/en'
|
||||
import eleLocaleZhCN from 'element-ui/lib/locale/lang/zh-CN'
|
||||
```
|
||||
|
||||
### 应用菜单
|
||||
应用菜单的国际化文件按照语言进行目录划分,每个目录里有三大操作系统对应的 JSON 文件:
|
||||
- darwin.json
|
||||
- linux.json
|
||||
- win32.json
|
||||
|
||||
### 主界面
|
||||
主界面和 Element UI 都是用 i18next 作为翻译支持库,所以你可能需要简单了解一下它的[使用方法](https://www.i18next.com/overview/getting-started)。
|
||||
主界面的配置同样按照语言划分目录:`src/shared/locales`,如:`src/shared/locales/en-US` 和 `src/shared/locales/zh-CN`。
|
||||
目录里面有按业务模块划分的语言文件:
|
||||
- about.js
|
||||
- app.js
|
||||
- edit.js
|
||||
- help.js
|
||||
- index.js
|
||||
- menu.js
|
||||
- preferences.js
|
||||
- subnav.js
|
||||
- task.js
|
||||
- window.js
|
||||
@@ -0,0 +1,37 @@
|
||||
# Motrix Contributing Guide
|
||||
|
||||
## 🌍 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://electronjs.org/docs/api/locales).
|
||||
|
||||
The internationalization of Motrix is divided into three parts:
|
||||
- Element UI
|
||||
- Application 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
|
||||
```
|
||||
import eleLocaleEn from 'element-ui/lib/locale/lang/en'
|
||||
import eleLocaleZhCN from 'element-ui/lib/locale/lang/zh-CN'
|
||||
```
|
||||
|
||||
### Application Menu
|
||||
The internationalization files of the application menu are divided into directories according to the **locale**. Each directory has three JSON files corresponding to the OS:
|
||||
- darwin.json
|
||||
- linux.json
|
||||
- win32.json
|
||||
|
||||
### Main Interface
|
||||
Both the main interface and the Element UI use [i18next](https://www.i18next.com/overview/getting-started) as the translation support library, so you may need to take a brief look at how to use it.
|
||||
The configuration of the main interface is also divided into directories according to the **locale**: `src/shared/locales`, such as: `src/shared/locales/en-US` and `src/shared/locales/zh-CN`.
|
||||
There are language files in the directory divided by business modules:
|
||||
- about.js
|
||||
- app.js
|
||||
- edit.js
|
||||
- help.js
|
||||
- index.js
|
||||
- menu.js
|
||||
- preferences.js
|
||||
- subnav.js
|
||||
- task.js
|
||||
- window.js
|
||||
+24
-7
@@ -13,28 +13,32 @@
|
||||
|
||||
Motirx 是一款全能的下载工具,支持下载 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) 提供了已经编译好的稳定版安装包,当然你也可以自己克隆代码编译打包。
|
||||
[GitHub](https://github.com/agalwood/Motrix/releases) 和 [官网](https://motrix.app/zh-CN) 提供了已经编译好的稳定版安装包,当然你也可以自己克隆代码编译打包。
|
||||
|
||||
> 七牛CDN流量🔥烧不起,高峰时一天烧了110G的流量💸💸💸
|
||||
更新:macOS 用户支持 `brew cask` 安装,感谢 [Mitscherlich](https://github.com/Mitscherlich) 的 [PR](https://github.com/Homebrew/homebrew-cask/pull/59494)。
|
||||
|
||||
```bash
|
||||
brew update && brew cask install motrix
|
||||
```
|
||||
|
||||
## ✨ 特性
|
||||
- 🕹 简洁明了的图形操作界面
|
||||
- 🧲 支持BT和磁力链任务
|
||||
- 🤫 支持下载百度云盘资源
|
||||
- 🦄 支持BT和磁力链任务
|
||||
- 💾 支持下载百度云盘资源
|
||||
- 🎛 最高支持 10 个任务同时下载
|
||||
- 🚀 单任务最高支持 64 线程下载
|
||||
- 🕶 模拟用户代理UA
|
||||
- 🔔 下载完成后通知
|
||||
- 💻 支持触控栏快捷健 (Mac 专享)
|
||||
- 🗑 移除任务时可同时删除相关文件
|
||||
- 🌍 国际化(可选择简体中文或英文界面)
|
||||
- 🌍 国际化,[查看已可选的语言](#-国际化)
|
||||
- 🎏 ...
|
||||
|
||||
## 🖥 应用界面
|
||||

|
||||

|
||||
|
||||
## ⌨️ 本地开发
|
||||
|
||||
@@ -78,5 +82,18 @@ npm run build
|
||||
## 🤝 参与共建 [](http://makeapullrequest.com)
|
||||
如果你有兴趣参与共同开发,欢迎 FORK 和 PR。
|
||||
|
||||
## 🌍 国际化
|
||||
欢迎大家将 Motrix 翻译成更多的语言版本 🧐,开工之前请先阅读一下 [翻译指南](./CONTRIBUTING-CN.md#-翻译指南)。
|
||||
|
||||
| Key | Name | Status |
|
||||
|-------|:--------------------|:-------------|
|
||||
| de | German | 下版本发布 [@Schloemicher](https://github.com/Schloemicher) |
|
||||
| en-US | English | ✔️ |
|
||||
| fr | Français | 下版本发布 [@gpatarin](https://github.com/gpatarin) |
|
||||
| pt-BR | Portuguese (Brazil) | 下版本发布 [@andrenoberto](https://github.com/andrenoberto) |
|
||||
| tr | Türkçe | 下版本发布 [@abdullah](https://github.com/abdullah) |
|
||||
| zh-CN | 简体中文 | ✔️ |
|
||||
| zh-TW | 繁體中文 | 下版本发布 [@Yukaii](https://github.com/Yukaii) |
|
||||
|
||||
## 📜 开源许可
|
||||
基于 [MIT license](https://opensource.org/licenses/MIT) 许可进行开源。
|
||||
|
||||
@@ -9,30 +9,36 @@
|
||||
|
||||
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, Baidu Net Disk, 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](http://motrix.app/support/issues) (zh-CN)
|
||||
|
||||
## 💽 Installation
|
||||
Download from [GitHub Releases](https://github.com/agalwood/Motrix/releases) and install it.
|
||||
|
||||
Update: macOS user support `brew cask` installation, thanks to [PR](https://github.com/Homebrew/homebrew-cask/pull/59494) of [Mitscherlich](https://github.com/Mitscherlich).
|
||||
|
||||
```bash
|
||||
brew update && brew cask install motrix
|
||||
```
|
||||
|
||||
## ✨ 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
|
||||
- 💾 Supports downloading Baidu Net Disk
|
||||
- 🎛 Up to 10 concurrent download tasks
|
||||
- 🚀 Supports 64 threads in a single task
|
||||
- 🕶 Mock User-Agent
|
||||
- 🔔 Download completed Notification
|
||||
- 💻 Ready for Touch Bar (Mac only)
|
||||
- 🗑 Delete related files when removing tasks (optional)
|
||||
- 🌍 I18n, currently available Simplified Chinese & English.
|
||||
- 🌍 I18n, [View supported languages](#-internationalization).
|
||||
- 🎏 ...
|
||||
|
||||
## 🖥 User Interface
|
||||

|
||||

|
||||
|
||||
## ⌨️ Development
|
||||
|
||||
@@ -57,7 +63,7 @@ npm run dev
|
||||
```bash
|
||||
npm 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/)
|
||||
@@ -68,7 +74,20 @@ After build finish, you can see the compiled packaged application file in the `r
|
||||
Development Roadmap see: [Trello](https://trello.com/b/qNUzA0bv/motrix)
|
||||
|
||||
## 🤝 Contribute [](http://makeapullrequest.com)
|
||||
If you are interested in participating in joint development, Fork and PR are welcome.
|
||||
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 |
|
||||
|-------|:--------------------|:-------------|
|
||||
| de | German | Next Release [@Schloemicher](https://github.com/Schloemicher) |
|
||||
| en-US | English | ✔️ |
|
||||
| fr | Français | Next Release [@gpatarin](https://github.com/gpatarin) |
|
||||
| pt-BR | Portuguese (Brazil) | Next Release [@andrenoberto](https://github.com/andrenoberto) |
|
||||
| tr | Türkçe | Next Release [@abdullah](https://github.com/abdullah) |
|
||||
| zh-CN | 简体中文 | ✔️ |
|
||||
| zh-TW | 繁體中文 | Next Release [@Yukaii](https://github.com/Yukaii) |
|
||||
|
||||
## 📜 License
|
||||
[MIT](https://opensource.org/licenses/MIT) Copyright (c) 2018-present Dr_rOot
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 59 KiB |
@@ -33,7 +33,7 @@
|
||||
# 单个任务下载速度限制, 默认:0
|
||||
#@max-download-limit=0
|
||||
# 整体上传速度限制, 运行时可修改, 默认:0
|
||||
#@max-overall-upload-limit=0
|
||||
max-overall-upload-limit=128K
|
||||
# 单个任务上传速度限制, 默认:0
|
||||
#@max-upload-limit=0
|
||||
# 禁用IPv6, 默认:false
|
||||
|
||||
@@ -33,7 +33,7 @@ file-allocation=trunc
|
||||
# 单个任务下载速度限制, 默认:0
|
||||
#@max-download-limit=0
|
||||
# 整体上传速度限制, 运行时可修改, 默认:0
|
||||
#@max-overall-upload-limit=0
|
||||
max-overall-upload-limit=128K
|
||||
# 单个任务上传速度限制, 默认:0
|
||||
#@max-upload-limit=0
|
||||
# 禁用IPv6, 默认:false
|
||||
|
||||
@@ -33,7 +33,7 @@ file-allocation=falloc
|
||||
# 单个任务下载速度限制, 默认:0
|
||||
#@max-download-limit=0
|
||||
# 整体上传速度限制, 运行时可修改, 默认:0
|
||||
#@max-overall-upload-limit=0
|
||||
max-overall-upload-limit=128K
|
||||
# 单个任务上传速度限制, 默认:0
|
||||
#@max-upload-limit=0
|
||||
# 禁用IPv6, 默认:false
|
||||
|
||||
Generated
+3250
-976
File diff suppressed because it is too large
Load Diff
+55
-27
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Motrix",
|
||||
"version": "1.1.3",
|
||||
"version": "1.2.2",
|
||||
"description": "A full-featured download manager",
|
||||
"homepage": "https://motrix.app",
|
||||
"author": {
|
||||
@@ -32,6 +32,14 @@
|
||||
"build": {
|
||||
"productName": "Motrix",
|
||||
"appId": "net.agalwood.Motrix",
|
||||
"fileAssociations": [
|
||||
{
|
||||
"ext": "torrent",
|
||||
"mimeType": "application/x-bittorrent",
|
||||
"name": "Torrent",
|
||||
"role": "Viewer"
|
||||
}
|
||||
],
|
||||
"asar": true,
|
||||
"directories": {
|
||||
"output": "release"
|
||||
@@ -88,9 +96,27 @@
|
||||
},
|
||||
"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,6 +131,7 @@
|
||||
"allowToChangeInstallationDirectory": true
|
||||
},
|
||||
"linux": {
|
||||
"category": "Network",
|
||||
"target": [
|
||||
"deb",
|
||||
"snap",
|
||||
@@ -132,30 +159,31 @@
|
||||
"@panter/vue-i18next": "^0.15.0",
|
||||
"aria2": "^4.0.3",
|
||||
"axios": "^0.18.0",
|
||||
"blob-util": "^2.0.2",
|
||||
"clipboard-polyfill": "^2.7.0",
|
||||
"electron-debug": "^2.1.0",
|
||||
"electron-is": "^3.0.0",
|
||||
"electron-log": "^2.2.17",
|
||||
"electron-updater": "^4.0.7",
|
||||
"element-ui": "^2.5.4",
|
||||
"electron-updater": "^4.0.8",
|
||||
"element-ui": "^2.6.2",
|
||||
"forever-monitor": "^1.7.1",
|
||||
"i18next": "^15.0.0",
|
||||
"i18next": "^15.0.6",
|
||||
"lodash": "^4.17.11",
|
||||
"normalize.css": "^8.0.1",
|
||||
"parse-torrent": "^6.1.2",
|
||||
"svg-innerhtml": "^1.1.0",
|
||||
"vue": "^2.6.4",
|
||||
"vue": "^2.6.10",
|
||||
"vue-electron": "^1.0.6",
|
||||
"vue-router": "^3.0.2",
|
||||
"vuex": "^3.1.0",
|
||||
"vuex-router-sync": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^3.4.0",
|
||||
"@vue/cli-plugin-eslint": "^3.4.0",
|
||||
"@vue/cli-service": "^3.4.0",
|
||||
"@vue/cli-plugin-babel": "^3.5.1",
|
||||
"@vue/cli-plugin-eslint": "^3.5.1",
|
||||
"@vue/cli-service": "^3.5.1",
|
||||
"@vue/eslint-config-standard": "^4.0.0",
|
||||
"ajv": "^6.9.1",
|
||||
"ajv": "^6.10.0",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"babel-loader": "^7.1.4",
|
||||
@@ -166,28 +194,29 @@
|
||||
"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",
|
||||
"chalk": "^2.4.2",
|
||||
"copy-webpack-plugin": "^5.0.1",
|
||||
"cross-env": "^5.1.6",
|
||||
"css-loader": "^1.0.1",
|
||||
"del": "^3.0.0",
|
||||
"css-loader": "^2.1.1",
|
||||
"del": "^4.0.0",
|
||||
"devtron": "^1.4.0",
|
||||
"electron": "^4.0.4",
|
||||
"electron": "^4.1.1",
|
||||
"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": "^5.15.3",
|
||||
"eslint-config-standard": "^12.0.0",
|
||||
"eslint-friendly-formatter": "^4.0.1",
|
||||
"eslint-loader": "^2.1.2",
|
||||
"eslint-plugin-html": "^4.0.6",
|
||||
"eslint-plugin-import": "^2.16.0",
|
||||
"eslint-plugin-node": "^7.0.1",
|
||||
"eslint-plugin-node": "^8.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",
|
||||
"eslint-plugin-vue": "^5.2.2",
|
||||
"file-loader": "^3.0.1",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"mini-css-extract-plugin": "0.5.0",
|
||||
"multispinner": "^0.2.1",
|
||||
@@ -197,15 +226,14 @@
|
||||
"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-loader": "^15.7.0",
|
||||
"vue-style-loader": "^4.1.2",
|
||||
"vue-template-compiler": "^2.6.4",
|
||||
"webpack": "^4.29.3",
|
||||
"vue-template-compiler": "^2.6.10",
|
||||
"webpack": "^4.29.6",
|
||||
"webpack-cli": "^3.2.3",
|
||||
"webpack-dev-server": "^3.1.14",
|
||||
"webpack-dev-server": "^3.2.1",
|
||||
"webpack-hot-middleware": "^2.24.3",
|
||||
"webpack-merge": "^4.1.4"
|
||||
"webpack-merge": "^4.2.1"
|
||||
}
|
||||
}
|
||||
|
||||
+99
-12
@@ -1,9 +1,12 @@
|
||||
import { EventEmitter } from 'events'
|
||||
import { app, shell, dialog, ipcMain } from 'electron'
|
||||
import is from 'electron-is'
|
||||
import { readFile } from 'fs'
|
||||
import { extname, basename } from 'path'
|
||||
|
||||
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 UpdateManager from './core/UpdateManager'
|
||||
import EnergyManager from './core/EnergyManager'
|
||||
@@ -11,19 +14,21 @@ 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'
|
||||
|
||||
export default class Application extends EventEmitter {
|
||||
constructor () {
|
||||
super()
|
||||
|
||||
this.exceptionHandler = new ExceptionHandler()
|
||||
|
||||
this.isReady = false
|
||||
this.init()
|
||||
}
|
||||
|
||||
init () {
|
||||
this.configManager = new ConfigManager()
|
||||
|
||||
this.locale = this.configManager.getLocale()
|
||||
this.localeManager = setupLocaleManager(this.locale)
|
||||
this.i18n = this.localeManager.getI18n()
|
||||
|
||||
this.windowManager = new WindowManager({
|
||||
userConfig: this.configManager.getUserConfig()
|
||||
@@ -40,6 +45,8 @@ export default class Application extends EventEmitter {
|
||||
|
||||
this.touchBarManager = new TouchBarManager()
|
||||
|
||||
this.trayManager = new TrayManager()
|
||||
|
||||
this.energyManager = new EnergyManager()
|
||||
|
||||
this.initUpdaterManager()
|
||||
@@ -54,12 +61,11 @@ export default class Application extends EventEmitter {
|
||||
try {
|
||||
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 })
|
||||
}, () => {
|
||||
setTimeout(() => {
|
||||
app.quit()
|
||||
@@ -74,9 +80,29 @@ export default class Application extends EventEmitter {
|
||||
|
||||
showPage (page) {
|
||||
const win = this.windowManager.openWindow(page)
|
||||
win.once('ready-to-show', () => {
|
||||
this.isReady = true
|
||||
this.emit('ready')
|
||||
})
|
||||
this.touchBarManager.setup(page, win)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
@@ -120,8 +146,33 @@ export default class Application extends EventEmitter {
|
||||
if (is.dev() || is.mas()) {
|
||||
return
|
||||
}
|
||||
|
||||
this.show()
|
||||
|
||||
this.protocolManager.handle(url)
|
||||
this.showPage('index')
|
||||
}
|
||||
|
||||
handleFile (filePath) {
|
||||
if (!filePath) {
|
||||
return
|
||||
}
|
||||
|
||||
if (extname(filePath).toLowerCase() !== '.torrent') {
|
||||
return
|
||||
}
|
||||
|
||||
this.show()
|
||||
|
||||
const fileName = basename(filePath)
|
||||
readFile(filePath, (err, data) => {
|
||||
if (err) {
|
||||
logger.warn(`[Motrix] read file error: ${filePath}`, err.message)
|
||||
return
|
||||
}
|
||||
const file = Buffer.from(data).toString('base64')
|
||||
const args = [fileName, file]
|
||||
this.sendCommandToAll('application:new-bt-task-with-file', ...args)
|
||||
})
|
||||
}
|
||||
|
||||
initUpdaterManager () {
|
||||
@@ -184,8 +235,12 @@ export default class Application extends EventEmitter {
|
||||
app.exit()
|
||||
})
|
||||
|
||||
this.on('application:show', (page = 'index') => {
|
||||
this.showPage(page)
|
||||
this.on('application:show', (page) => {
|
||||
this.show(page)
|
||||
})
|
||||
|
||||
this.on('application:hide', (page) => {
|
||||
this.hide(page)
|
||||
})
|
||||
|
||||
this.on('application:reset', () => {
|
||||
@@ -198,7 +253,35 @@ export default class Application extends EventEmitter {
|
||||
})
|
||||
|
||||
this.on('application:change-locale', (locale) => {
|
||||
this.menuManager.setup(locale)
|
||||
logger.info('[Motrix] application:change-locale===>', locale)
|
||||
this.localeManager.changeLanguageByLocale(locale)
|
||||
.then(() => {
|
||||
this.menuManager.setup(locale)
|
||||
this.trayManager.setup(locale)
|
||||
})
|
||||
})
|
||||
|
||||
this.on('application:open-file', (event) => {
|
||||
dialog.showOpenDialog({
|
||||
properties: ['openFile'],
|
||||
filters: [
|
||||
{
|
||||
name: 'Torrent',
|
||||
extensions: ['torrent']
|
||||
}
|
||||
]
|
||||
}, (filePaths) => {
|
||||
if (!filePaths || filePaths.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const [filePath] = filePaths
|
||||
this.handleFile(filePath)
|
||||
})
|
||||
})
|
||||
|
||||
this.on('application:clear-recent-tasks', () => {
|
||||
app.clearRecentDocuments()
|
||||
})
|
||||
|
||||
this.on('help:official-website', () => {
|
||||
@@ -231,5 +314,9 @@ export default class Application extends EventEmitter {
|
||||
ipcMain.on('update-menu-states', (event, visibleStates, enabledStates, checkedStates) => {
|
||||
this.menuManager.updateStates(visibleStates, enabledStates, checkedStates)
|
||||
})
|
||||
|
||||
ipcMain.on('download-status-change', (event, status) => {
|
||||
this.trayManager.updateStatus(status)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
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 { parseArgv } from './utils'
|
||||
|
||||
const EMPTY_STRING = ''
|
||||
|
||||
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()
|
||||
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) { // Windows, Linux
|
||||
this.file = parseArgv(argv)
|
||||
this.sendFileToApplication()
|
||||
}
|
||||
})
|
||||
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
init () {
|
||||
this.exceptionHandler = new ExceptionHandler()
|
||||
|
||||
this.handleAppEvents()
|
||||
}
|
||||
|
||||
handleAppEvents () {
|
||||
this.handleOpenUrl()
|
||||
this.handleOpenFile()
|
||||
|
||||
this.handelAppReady()
|
||||
this.handleAppWillQuit()
|
||||
}
|
||||
|
||||
/**
|
||||
* handleOpenUrl
|
||||
* "name": "Motrix Protocol",
|
||||
* "schemes": ["mo", "motrix"]
|
||||
*/
|
||||
handleOpenUrl () {
|
||||
if (is.mas()) {
|
||||
return
|
||||
}
|
||||
app.on('open-url', (event, url) => {
|
||||
logger.info(`[Motrix] open-url path: ${url}`)
|
||||
event.preventDefault()
|
||||
this.url = url
|
||||
if (this.url && global.application && global.application.isReady) {
|
||||
global.application.handleProtocol(this.url)
|
||||
this.url = EMPTY_STRING
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* handleOpenFile [WIP]
|
||||
* handle open torrent file
|
||||
*/
|
||||
handleOpenFile () {
|
||||
// macOS
|
||||
if (is.macOS()) {
|
||||
app.on('open-file', (event, path) => {
|
||||
logger.info(`[Motrix] open-file path: ${path}`)
|
||||
event.preventDefault()
|
||||
this.file = path
|
||||
this.sendFileToApplication()
|
||||
})
|
||||
} else if (process.argv.length > 1) { // Windows, Linux
|
||||
this.file = parseArgv(process.argv)
|
||||
this.sendFileToApplication()
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
global.application.start('index')
|
||||
|
||||
global.application.on('ready', () => {
|
||||
if (this.url) {
|
||||
global.application.handleProtocol(this.url)
|
||||
}
|
||||
|
||||
if (this.file) {
|
||||
global.application.handleFile(this.file)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
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()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -13,17 +13,5 @@ export default {
|
||||
},
|
||||
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`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,10 @@ export default class ConfigManager {
|
||||
this.initUserConfig()
|
||||
}
|
||||
|
||||
/**
|
||||
* some aria2 conf
|
||||
* https://aria2.github.io/manual/en/html/aria2c.html
|
||||
*/
|
||||
initSystemConfig () {
|
||||
this.systemConfig = new Store({
|
||||
name: 'system',
|
||||
@@ -52,7 +56,7 @@ export default class ConfigManager {
|
||||
defaults: {
|
||||
'resume-all-when-app-launched': false,
|
||||
'task-notification': true,
|
||||
'hide-app-menu': false,
|
||||
'hide-app-menu': is.windows() || is.linux(),
|
||||
'new-task-show-downloading': true,
|
||||
'auto-check-for-updates': false,
|
||||
'update-channel': 'latest',
|
||||
|
||||
+27
-8
@@ -6,6 +6,7 @@ import { existsSync } from 'fs'
|
||||
import { resolve, join } from 'path'
|
||||
import forever from 'forever-monitor'
|
||||
import logger from './Logger'
|
||||
import { getI18n } from '@/ui/Locale'
|
||||
import {
|
||||
getEngineBin,
|
||||
getSessionPath,
|
||||
@@ -16,6 +17,9 @@ export default class Engine {
|
||||
static instance = null
|
||||
|
||||
constructor (options = {}) {
|
||||
this.options = options
|
||||
|
||||
this.i18n = getI18n()
|
||||
this.systemConfig = options.systemConfig
|
||||
this.userConfig = options.userConfig
|
||||
}
|
||||
@@ -30,14 +34,14 @@ export default class Engine {
|
||||
|
||||
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)
|
||||
if (!binIsExist) {
|
||||
logger.error('[Motrix] engine bin is not exist===>', binPath)
|
||||
throw new Error('引擎文件缺失,请重新安装: (')
|
||||
throw new Error(this.i18n.t('app.engine-missing-message'))
|
||||
}
|
||||
|
||||
let confPath = join(basePath, '/engine/aria2.conf')
|
||||
@@ -60,7 +64,7 @@ export default class Engine {
|
||||
const sh = this.getStartSh()
|
||||
logger.info('[Motrix] Engine start sh===>', sh)
|
||||
this.instance = forever.start(sh, {
|
||||
max: 3,
|
||||
max: 10,
|
||||
parser: function (command, args) {
|
||||
return {
|
||||
command: command,
|
||||
@@ -73,13 +77,29 @@ export default class Engine {
|
||||
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 error===> ${err}`)
|
||||
})
|
||||
|
||||
this.instance.on('error', (err) => {
|
||||
logger.info(`[Motrix] Engine has exited after 3 restarts===> ${err}`)
|
||||
this.instance.on('start', function (process, data) {
|
||||
logger.info(`[Motrix] Engine started===>`)
|
||||
})
|
||||
|
||||
this.instance.on('stop', function (process) {
|
||||
logger.info(`[Motrix] Engine stopped===>`)
|
||||
})
|
||||
|
||||
this.instance.on('restart', function (forever) {
|
||||
logger.info(`[Motrix] Engine exit===>`)
|
||||
})
|
||||
|
||||
this.instance.on('exit:code', function (code) {
|
||||
logger.info(`[Motrix] Engine exit===> ${code}`)
|
||||
})
|
||||
|
||||
// this.instance.on('stderr', (data) => {
|
||||
// logger.info(`[Motrix] Engine stderr===> ${data}`)
|
||||
// })
|
||||
}
|
||||
|
||||
stop () {
|
||||
@@ -87,7 +107,6 @@ export default class Engine {
|
||||
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)
|
||||
|
||||
@@ -3,5 +3,6 @@ import logger from 'electron-log'
|
||||
|
||||
logger.transports.file.level = is.production() ? 'warn' : 'info'
|
||||
logger.info('Logger init')
|
||||
logger.warn('[Motrix] Logger init')
|
||||
|
||||
export default logger
|
||||
|
||||
@@ -37,6 +37,6 @@ export default class ProtocolManager extends EventEmitter {
|
||||
// 如果按顺序传递,那 url 的 query string 就要求有序的了
|
||||
// const query = queryString.parse(parsed.query)
|
||||
const args = []
|
||||
global.application.sendCommand(command, ...args)
|
||||
global.application.sendCommandToAll(command, ...args)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ 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,6 +14,7 @@ export default class UpdateManager extends EventEmitter {
|
||||
constructor (options = {}) {
|
||||
super()
|
||||
this.options = options
|
||||
this.i18n = getI18n()
|
||||
|
||||
this.updater = autoUpdater
|
||||
this.updater.autoDownload = false
|
||||
@@ -48,9 +50,9 @@ 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) {
|
||||
@@ -62,8 +64,8 @@ export default class UpdateManager extends EventEmitter {
|
||||
updateNotAvailable (event, info) {
|
||||
this.emit('update-not-available', info)
|
||||
dialog.showMessageBox({
|
||||
title: '没有更新的版本',
|
||||
message: '您目前使用的已是最新版本'
|
||||
title: this.i18n.t('app.check-for-updates-title'),
|
||||
message: this.i18n.t('app.update-not-available-message')
|
||||
})
|
||||
}
|
||||
|
||||
@@ -84,8 +86,8 @@ 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')
|
||||
}, () => {
|
||||
this.emit('will-updated')
|
||||
setImmediate(() => {
|
||||
@@ -96,8 +98,8 @@ export default class UpdateManager extends EventEmitter {
|
||||
|
||||
updateError (event, error) {
|
||||
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('update-error-message') : (error.stack || error).toString()
|
||||
this.updater.logger.warn(`[Motrix] update-error: ${msg}`)
|
||||
dialog.showErrorBox(msg)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-63
@@ -1,8 +1,7 @@
|
||||
import { app } from 'electron'
|
||||
import is from 'electron-is'
|
||||
|
||||
import logger from './core/Logger'
|
||||
import Application from './Application'
|
||||
import Launcher from './Launcher'
|
||||
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
|
||||
@@ -12,67 +11,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()
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
{
|
||||
"menu": [
|
||||
{
|
||||
"id": "menu.app",
|
||||
"submenu": [
|
||||
{ "id": "app.about", "command": "application:about", "command-before": "application:show,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,index" },
|
||||
{ "id": "task.new-bt-task", "command": "application:new-bt-task", "command-arg": "torrent", "command-after": "application:show,index" },
|
||||
{ "id": "task.open-file", "command": "application:open-file", "command-before": "application:show,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" },
|
||||
{ "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" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"menu": [
|
||||
{
|
||||
"id": "menu.file",
|
||||
"submenu": [
|
||||
{ "id": "app.about", "command": "application:about", "command-before": "application:show,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": "index" },
|
||||
{ "type": "separator" },
|
||||
{ "id": "app.quit", "role": "quit" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "menu.task",
|
||||
"submenu": [
|
||||
{ "id": "task.new-task", "command": "application:new-task", "command-after": "application:show,index" },
|
||||
{ "id": "task.new-bt-task", "command": "application:new-bt-task", "command-arg": "torrent", "command-after": "application:show,index" },
|
||||
{ "id": "task.open-file", "command": "application:open-file", "command-before": "application:show,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": "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" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
[
|
||||
{ "id": "task.new-task", "command": "application:new-task", "command-after": "application:show,index" },
|
||||
{ "id": "task.new-bt-task", "command": "application:new-bt-task", "command-arg": "torrent", "command-after": "application:show,index" },
|
||||
{ "id": "task.open-file", "command": "application:open-file", "command-before": "application:show,index" },
|
||||
{ "type": "separator" },
|
||||
{ "id": "app.show", "command": "application:show", "command-arg": "index" },
|
||||
{ "id": "help.manual", "command": "help:manual" },
|
||||
{ "type": "separator" },
|
||||
{ "id": "app.preferences", "command": "application:preferences", "command-before": "application:show,index" },
|
||||
{ "id": "app.quit", "role": "quit" }
|
||||
]
|
||||
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"menu": [
|
||||
{
|
||||
"id": "menu.file",
|
||||
"submenu": [
|
||||
{ "id": "app.about", "command": "application:about", "command-before": "application:show,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": "index" },
|
||||
{ "type": "separator" },
|
||||
{ "id": "app.quit", "role": "quit" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "menu.task",
|
||||
"submenu": [
|
||||
{ "id": "task.new-task", "command": "application:new-task", "command-after": "application:show,index" },
|
||||
{ "id": "task.new-bt-task", "command": "application:new-bt-task", "command-arg": "torrent", "command-after": "application:show,index" },
|
||||
{ "id": "task.open-file", "command": "application:open-file", "command-before": "application:show,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" },
|
||||
{ "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" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
+21
-20
@@ -6,29 +6,24 @@ import {
|
||||
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`)
|
||||
}
|
||||
load () {
|
||||
let template = require(`../menus/${process.platform}.json`)
|
||||
this.template = template['menu']
|
||||
}
|
||||
|
||||
@@ -38,15 +33,21 @@ export default class MenuManager extends EventEmitter {
|
||||
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)
|
||||
}
|
||||
|
||||
rebuild () {
|
||||
this.setup()
|
||||
}
|
||||
|
||||
updateStates (visibleStates, enabledStates, checkedStates) {
|
||||
|
||||
@@ -1,3 +1,97 @@
|
||||
export default class TrayManager {
|
||||
import { EventEmitter } from 'events'
|
||||
import { join } from 'path'
|
||||
import { Tray, Menu } from 'electron'
|
||||
import is from 'electron-is'
|
||||
import { translateTemplate } from '../utils/menu'
|
||||
import { getI18n } from '@/ui/Locale'
|
||||
|
||||
let tray = null
|
||||
|
||||
export default class TrayManager extends EventEmitter {
|
||||
constructor (options = {}) {
|
||||
super()
|
||||
|
||||
this.i18n = getI18n()
|
||||
|
||||
this.menu = null
|
||||
|
||||
this.load()
|
||||
this.init()
|
||||
this.setup()
|
||||
this.handleEvents()
|
||||
}
|
||||
|
||||
load () {
|
||||
this.template = require(`../menus/tray.json`)
|
||||
|
||||
if (is.macOS()) {
|
||||
this.normalIcon = join(__static, './mo-tray-normal.png')
|
||||
this.activeIcon = join(__static, './mo-tray-active.png')
|
||||
} else {
|
||||
this.normalIcon = join(__static, './mo-tray-colorful-normal.png')
|
||||
this.activeIcon = join(__static, './mo-tray-colorful-active.png')
|
||||
}
|
||||
}
|
||||
|
||||
build () {
|
||||
const keystrokesByCommand = {}
|
||||
for (let 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)
|
||||
}
|
||||
|
||||
setup () {
|
||||
this.build()
|
||||
|
||||
/**
|
||||
* Linux requires setContextMenu to be called
|
||||
* in order for the context menu to populate correctly
|
||||
*/
|
||||
if (process.platform === 'linux') {
|
||||
tray.setContextMenu(this.menu)
|
||||
}
|
||||
}
|
||||
|
||||
init () {
|
||||
tray = new Tray(this.normalIcon)
|
||||
tray.setToolTip('Motrix')
|
||||
}
|
||||
|
||||
handleEvents () {
|
||||
tray.on('click', this.handleTrayClick)
|
||||
tray.on('double-click', this.handleTrayDbClick)
|
||||
tray.on('right-click', this.handleTrayRightClick)
|
||||
|
||||
tray.on('drop-files', this.handleTrayDropFile)
|
||||
}
|
||||
|
||||
handleTrayClick = (event) => {
|
||||
event.preventDefault()
|
||||
global.application.toggle()
|
||||
}
|
||||
|
||||
handleTrayDbClick = (event) => {
|
||||
event.preventDefault()
|
||||
global.application.show()
|
||||
}
|
||||
|
||||
handleTrayRightClick = (event) => {
|
||||
event.preventDefault()
|
||||
tray.popUpContextMenu(this.menu)
|
||||
}
|
||||
|
||||
handleTrayDropFile = (event, files) => {
|
||||
global.application.show()
|
||||
global.application.handleFile(files[0])
|
||||
}
|
||||
|
||||
updateStatus (status) {
|
||||
const icon = status ? this.activeIcon : this.normalIcon
|
||||
tray.setImage(icon)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { join } from 'path'
|
||||
import { EventEmitter } from 'events'
|
||||
import { app, shell, BrowserWindow } from 'electron'
|
||||
import is from 'electron-is'
|
||||
import pageConfig from '../configs/page'
|
||||
import logger from '../core/Logger'
|
||||
|
||||
const defaultBrowserOptions = {
|
||||
titleBarStyle: 'hiddenInset',
|
||||
@@ -19,9 +22,9 @@ export default class WindowManager extends EventEmitter {
|
||||
|
||||
this.willQuit = false
|
||||
|
||||
app.on('before-quit', () => {
|
||||
this.setWillQuit(true)
|
||||
})
|
||||
this.handleBeforeQuit()
|
||||
|
||||
this.handleAllWindowClosed()
|
||||
}
|
||||
|
||||
setWillQuit (flag) {
|
||||
@@ -32,8 +35,15 @@ 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
@@ -65,7 +75,7 @@ export default class WindowManager extends EventEmitter {
|
||||
window.show()
|
||||
})
|
||||
|
||||
if (options.bindCloseToHide && process.platform === 'darwin') {
|
||||
if (options.bindCloseToHide) {
|
||||
this.bindCloseToHide(page, window)
|
||||
}
|
||||
|
||||
@@ -116,15 +126,61 @@ export default class WindowManager extends EventEmitter {
|
||||
})
|
||||
}
|
||||
|
||||
showWindow (page) {
|
||||
const window = this.getWindow(page)
|
||||
if (!window) {
|
||||
return
|
||||
}
|
||||
window.show()
|
||||
}
|
||||
|
||||
hideWindow (page) {
|
||||
const window = this.getWindow(page)
|
||||
if (!window) {
|
||||
return
|
||||
}
|
||||
window.hide()
|
||||
}
|
||||
|
||||
hideAllWindow () {
|
||||
this.getWindowList().forEach((window) => {
|
||||
window.hide()
|
||||
})
|
||||
}
|
||||
|
||||
toggleWindow (page) {
|
||||
const window = this.getWindow(page)
|
||||
if (!window) {
|
||||
return
|
||||
}
|
||||
if (window.isVisible()) {
|
||||
window.hide()
|
||||
} else {
|
||||
window.show()
|
||||
}
|
||||
}
|
||||
|
||||
getFocusedWindow () {
|
||||
return BrowserWindow.getFocusedWindow()
|
||||
}
|
||||
|
||||
handleBeforeQuit () {
|
||||
app.on('before-quit', () => {
|
||||
this.setWillQuit(true)
|
||||
})
|
||||
}
|
||||
|
||||
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] sendCommandTo===>', window, command, ...args)
|
||||
window.webContents.send('command', command, ...args)
|
||||
}
|
||||
|
||||
|
||||
+19
-2
@@ -1,6 +1,7 @@
|
||||
import { app } from 'electron'
|
||||
import is from 'electron-is'
|
||||
import { resolve } from 'path'
|
||||
import { existsSync, lstatSync } from 'fs'
|
||||
import logger from '../core/Logger'
|
||||
import engineBinMap from '../configs/engine'
|
||||
|
||||
@@ -44,17 +45,33 @@ 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 isDirectory (path) {
|
||||
return existsSync(path) && lstatSync(path).isDirectory()
|
||||
}
|
||||
|
||||
export function parseArgv (argv) {
|
||||
let arg = argv[1]
|
||||
if (!arg || isDirectory(arg)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (is.linux()) {
|
||||
arg = arg.replace('file://', '')
|
||||
}
|
||||
return arg
|
||||
}
|
||||
|
||||
+16
-6
@@ -71,19 +71,29 @@ function findById (template, id) {
|
||||
return null
|
||||
}
|
||||
|
||||
export function translateTemplate (template, keystrokesByCommand) {
|
||||
export function translateTemplate (template, keystrokesByCommand, i18n) {
|
||||
for (let i in template) {
|
||||
let 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,7 +106,7 @@ export function handleCommand (item) {
|
||||
? [item.command, item['command-arg']]
|
||||
: [item.command]
|
||||
|
||||
global.application.sendCommand(...args)
|
||||
global.application.sendCommandToAll(...args)
|
||||
|
||||
handleCommandAfter(item)
|
||||
}
|
||||
@@ -108,7 +118,7 @@ function handleCommandBefore (item) {
|
||||
}
|
||||
const [ command, ...args ] = item['command-before'].split(',')
|
||||
console.log('handleCommandBefore==2=>', command, ...args)
|
||||
global.application.sendCommand(command, ...args)
|
||||
global.application.sendCommandToAll(command, ...args)
|
||||
}
|
||||
|
||||
function handleCommandAfter (item) {
|
||||
@@ -118,7 +128,7 @@ function handleCommandAfter (item) {
|
||||
}
|
||||
const [ command, ...args ] = item['command-after'].split(',')
|
||||
console.log('handleCommandAfter==2=>', command, ...args)
|
||||
global.application.sendCommand(command, ...args)
|
||||
global.application.sendCommandToAll(command, ...args)
|
||||
}
|
||||
|
||||
function acceleratorForCommand (command, keystrokesByCommand) {
|
||||
|
||||
+12
-3
@@ -111,6 +111,15 @@ export default class Api {
|
||||
return this.client.call('getVersion')
|
||||
}
|
||||
|
||||
getGlobalOption () {
|
||||
return new Promise((resolve) => {
|
||||
this.client.call('getGlobalOption')
|
||||
.then((data) => {
|
||||
resolve(changeKeysToCamelCase(data))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
getGlobalStat () {
|
||||
return this.client.call('getGlobalStat')
|
||||
}
|
||||
@@ -146,7 +155,7 @@ export default class Api {
|
||||
}
|
||||
|
||||
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) => {
|
||||
@@ -165,13 +174,13 @@ export default class Api {
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<el-row class="copyright">
|
||||
<el-col :span="8" class="copyright-left">
|
||||
<el-col :span="6" class="copyright-left">
|
||||
<a target="_blank" href="https://motrix.app/" rel="noopener noreferrer">
|
||||
©2018 Motrix
|
||||
</a>
|
||||
</el-col>
|
||||
<el-col :span="16" class="copyright-right">
|
||||
<el-col :span="18" class="copyright-right">
|
||||
<a target="_blank" href="https://motrix.app/about" rel="noopener noreferrer">
|
||||
{{ $t('about.about') }}
|
||||
</a>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<el-aside width="78px" class="aside" :class="{ draggable: !isWindows() }">
|
||||
<el-aside width="78px" :class="['aside', { 'draggable': asideDraggable }]">
|
||||
<div class="aside-inner">
|
||||
<mo-logo-mini />
|
||||
<ul class="menu top-menu">
|
||||
@@ -39,11 +39,12 @@
|
||||
computed: {
|
||||
...mapState('app', {
|
||||
currentPage: state => state.currentPage
|
||||
})
|
||||
}),
|
||||
asideDraggable: function () {
|
||||
return is.macOS()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isRenderer: is.renderer,
|
||||
isWindows: is.windows,
|
||||
open (link) {
|
||||
this.$electron.shell.openExternal(link)
|
||||
},
|
||||
@@ -51,7 +52,7 @@
|
||||
this.$store.dispatch('app/showAddTaskDialog', taskType)
|
||||
},
|
||||
showAboutPanel () {
|
||||
// if (this.isRenderer()) {
|
||||
// if (is.renderer()) {
|
||||
// this.$electron.ipcRenderer.send('command', 'application:about')
|
||||
// } else {
|
||||
this.$store.dispatch('app/showAboutPanel')
|
||||
|
||||
@@ -3,6 +3,8 @@ import store from '@/store'
|
||||
import CommandManager from './CommandManager'
|
||||
import { Message } from 'element-ui'
|
||||
import { getLocaleManager } from '@/components/Locale'
|
||||
import { base64StringToBlob } from 'blob-util'
|
||||
import { buildFileList } from '@shared/utils'
|
||||
|
||||
const commands = new CommandManager()
|
||||
const i18n = getLocaleManager().getI18n()
|
||||
@@ -15,6 +17,16 @@ function showAddTask (taskType = 'uri') {
|
||||
store.dispatch('app/showAddTaskDialog', taskType)
|
||||
}
|
||||
|
||||
function showAddBtTaskWithFile (fileName, base64Data = '') {
|
||||
const blob = base64StringToBlob(base64Data, 'application/x-bittorrent')
|
||||
const file = new File([blob], fileName, { type: 'application/x-bittorrent' })
|
||||
const fileList = buildFileList(file)
|
||||
store.dispatch('app/showAddTaskDialog', 'torrent')
|
||||
setTimeout(() => {
|
||||
store.dispatch('app/addTaskAddTorrents', { fileList })
|
||||
}, 200)
|
||||
}
|
||||
|
||||
function navigateTaskList (status = 'active') {
|
||||
router.push({ path: `/task/${status}` })
|
||||
}
|
||||
@@ -58,6 +70,7 @@ function resumeAllTask () {
|
||||
commands.register('application:about', showAboutPanel)
|
||||
commands.register('application:new-task', showAddTask)
|
||||
commands.register('application:new-bt-task', showAddTask)
|
||||
commands.register('application:new-bt-task-with-file', showAddBtTaskWithFile)
|
||||
commands.register('application:task-list', navigateTaskList)
|
||||
commands.register('application:preferences', navigatePreferences)
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div v-if="false"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'mo-dragger',
|
||||
mounted () {
|
||||
this.preventDefault = ev => ev.preventDefault()
|
||||
let count = 0
|
||||
this.onDragEnter = (ev) => {
|
||||
if (count === 0) {
|
||||
this.$store.dispatch('app/showAddTaskDialog', 'torrent')
|
||||
}
|
||||
count++
|
||||
}
|
||||
|
||||
this.onDragLeave = (ev) => {
|
||||
count--
|
||||
if (count === 0) {
|
||||
this.$store.dispatch('app/hideAddTaskDialog')
|
||||
}
|
||||
}
|
||||
|
||||
this.onDrop = (ev) => {
|
||||
count = 0
|
||||
|
||||
const fileList = [...ev.dataTransfer.files]
|
||||
.map(item => ({ raw: item, name: item.name }))
|
||||
.filter(item => /\.torrent$/.test(item.name))
|
||||
if (!fileList.length) {
|
||||
this.$msg.error(this.$t('task.select-torrent'))
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('dragover', this.preventDefault)
|
||||
document.body.addEventListener('dragenter', this.onDragEnter)
|
||||
document.body.addEventListener('dragleave', this.onDragLeave)
|
||||
document.body.addEventListener('drop', this.onDrop)
|
||||
},
|
||||
destroyed () {
|
||||
document.removeEventListener('dragover', this.preventDefault)
|
||||
document.body.removeEventListener('dragenter', this.onDragEnter)
|
||||
document.body.removeEventListener('dragleave', this.onDragLeave)
|
||||
document.body.removeEventListener('drop', this.onDrop)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,32 +1,10 @@
|
||||
import i18next from 'i18next'
|
||||
import { getLanguage } from '@shared/locales'
|
||||
import resources from '@shared/locales/all'
|
||||
import LocaleManager from '@shared/locales/LocaleManager'
|
||||
|
||||
export class LocaleManager {
|
||||
constructor (options = {}) {
|
||||
this.options = options
|
||||
const localeManager = new LocaleManager({
|
||||
resources
|
||||
})
|
||||
|
||||
i18next.init({
|
||||
fallbackLng: 'en-US',
|
||||
resources
|
||||
})
|
||||
}
|
||||
|
||||
changeLanguage (lng) {
|
||||
i18next.changeLanguage(lng)
|
||||
}
|
||||
|
||||
changeLanguageByLocale (locale) {
|
||||
const lng = getLanguage(locale)
|
||||
this.changeLanguage(lng)
|
||||
}
|
||||
|
||||
getI18n () {
|
||||
return i18next
|
||||
}
|
||||
}
|
||||
|
||||
const localeManager = new LocaleManager()
|
||||
export function getLocaleManager () {
|
||||
return localeManager
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<mo-add-task :visible="addTaskVisible" :type="addTaskType" />
|
||||
<mo-about-panel :visible="aboutPanelVisible" />
|
||||
<mo-task-item-info :visible="taskItemInfoVisible" :task="currentTaskItem" />
|
||||
<mo-dragger />
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
@@ -17,6 +18,7 @@
|
||||
import Speedometer from '@/components/Speedometer/Speedometer'
|
||||
import AddTask from '@/components/Task/AddTask'
|
||||
import TaskItemInfo from '@/components/Task/TaskItemInfo'
|
||||
import Dragger from '@/components/Dragger/Index'
|
||||
|
||||
export default {
|
||||
name: 'mo-main',
|
||||
@@ -26,7 +28,8 @@
|
||||
[Subnav.name]: Subnav,
|
||||
[Speedometer.name]: Speedometer,
|
||||
[AddTask.name]: AddTask,
|
||||
[TaskItemInfo.name]: TaskItemInfo
|
||||
[TaskItemInfo.name]: TaskItemInfo,
|
||||
[Dragger.name]: Dragger
|
||||
},
|
||||
computed: {
|
||||
...mapState('app', {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
const queue = []
|
||||
const maxLength = 5
|
||||
|
||||
export default {
|
||||
install: function (Vue, Message, defaultOption = {}) {
|
||||
Vue.prototype.$msg = new Proxy(Message, {
|
||||
get (obj, prop) {
|
||||
return (arg) => {
|
||||
if (!(arg instanceof Object)) {
|
||||
arg = { message: arg }
|
||||
}
|
||||
const task = {
|
||||
run () {
|
||||
obj[prop]({
|
||||
...defaultOption,
|
||||
...arg,
|
||||
onClose (...data) {
|
||||
const currentTask = queue.pop()
|
||||
if (currentTask) {
|
||||
currentTask.run()
|
||||
}
|
||||
if (arg.onClose) {
|
||||
arg.onClose(...data)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (queue.length >= maxLength) {
|
||||
queue.pop()
|
||||
}
|
||||
queue.unshift(task)
|
||||
|
||||
if (queue.length === 1) {
|
||||
queue.pop().run()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import is from 'electron-is'
|
||||
import { mapState } from 'vuex'
|
||||
import api from '@/api'
|
||||
import {
|
||||
@@ -18,10 +19,17 @@
|
||||
|
||||
export default {
|
||||
name: 'mo-engine-client',
|
||||
data: function () {
|
||||
return {
|
||||
downloading: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isRenderer: () => is.renderer(),
|
||||
...mapState('app', {
|
||||
downloadSpeed: state => state.stat.downloadSpeed,
|
||||
interval: state => state.interval
|
||||
interval: state => state.interval,
|
||||
numActive: state => state.stat.numActive
|
||||
}),
|
||||
...mapState('task', {
|
||||
taskItemInfoVisible: state => state.taskItemInfoVisible,
|
||||
@@ -34,56 +42,70 @@
|
||||
watch: {
|
||||
downloadSpeed: function (val, oldVal) {
|
||||
showDownloadSpeedInDock(val)
|
||||
},
|
||||
numActive: function (val, oldVal) {
|
||||
this.downloading = val > 0
|
||||
},
|
||||
downloading: function (val, oldVal) {
|
||||
if (val !== oldVal && this.isRenderer) {
|
||||
this.$electron.ipcRenderer.send('download-status-change', val)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fetchTaskItem ({ gid }) {
|
||||
return api.fetchTaskItem({ gid })
|
||||
.catch((e) => {
|
||||
console.warn(`fetchTaskItem fail: ${e.message}`)
|
||||
})
|
||||
},
|
||||
onDownloadStart: function (event) {
|
||||
this.$store.dispatch('task/fetchList')
|
||||
this.$store.dispatch('app/resetInterval')
|
||||
console.log('aria2 onDownloadStart', event)
|
||||
const [{ gid }] = event
|
||||
api.fetchTaskItem({ gid })
|
||||
this.fetchTaskItem({ gid })
|
||||
.then((task) => {
|
||||
const taskName = getTaskName(task)
|
||||
const message = this.$t('task.download-start-message', { taskName })
|
||||
this.$message.info(message)
|
||||
this.$msg.info(message)
|
||||
})
|
||||
},
|
||||
onDownloadPause: function (event) {
|
||||
console.log('aria2 onDownloadPause')
|
||||
const [{ gid }] = event
|
||||
api.fetchTaskItem({ gid })
|
||||
this.fetchTaskItem({ gid })
|
||||
.then((task) => {
|
||||
const taskName = getTaskName(task)
|
||||
const message = this.$t('task.download-pause-message', { taskName })
|
||||
this.$message.info(message)
|
||||
this.$msg.info(message)
|
||||
})
|
||||
},
|
||||
onDownloadStop: function (event) {
|
||||
console.log('aria2 onDownloadStop')
|
||||
const [{ gid }] = event
|
||||
api.fetchTaskItem({ gid })
|
||||
this.fetchTaskItem({ gid })
|
||||
.then((task) => {
|
||||
const taskName = getTaskName(task)
|
||||
const message = this.$t('task.download-stop-message', { taskName })
|
||||
this.$message.info(message)
|
||||
this.$msg.info(message)
|
||||
})
|
||||
},
|
||||
onDownloadError: function (event) {
|
||||
console.log('aria2 onDownloadError', event)
|
||||
const [{ gid }] = event
|
||||
api.fetchTaskItem({ gid })
|
||||
this.fetchTaskItem({ gid })
|
||||
.then((task) => {
|
||||
const taskName = getTaskName(task)
|
||||
const message = this.$t('task.download-error-message', { taskName })
|
||||
this.$message.error(message)
|
||||
this.$msg.error(message)
|
||||
})
|
||||
},
|
||||
onDownloadComplete: function (event) {
|
||||
console.log('aria2 onDownloadComplete')
|
||||
this.$store.dispatch('task/fetchList')
|
||||
const [{ gid }] = event
|
||||
api.fetchTaskItem({ gid })
|
||||
this.fetchTaskItem({ gid })
|
||||
.then((task) => {
|
||||
this.showTaskCompleteNotify(task)
|
||||
})
|
||||
@@ -92,7 +114,7 @@
|
||||
console.log('aria2 onBtDownloadComplete')
|
||||
this.$store.dispatch('task/fetchList')
|
||||
const [{ gid }] = event
|
||||
api.fetchTaskItem({ gid })
|
||||
this.fetchTaskItem({ gid })
|
||||
.then((task) => {
|
||||
this.showTaskCompleteNotify(task)
|
||||
})
|
||||
@@ -109,7 +131,7 @@
|
||||
openDownloadDock(path)
|
||||
|
||||
const message = this.$t('task.download-complete-message', { taskName })
|
||||
this.$message.success(message)
|
||||
this.$msg.success(message)
|
||||
|
||||
/* eslint-disable no-new */
|
||||
const notify = new Notification(this.$t('task.download-complete-notify'), {
|
||||
@@ -129,7 +151,7 @@
|
||||
const taskName = getTaskName(task)
|
||||
|
||||
const message = this.$t('task.download-fail-message', { taskName })
|
||||
this.$message.success(message)
|
||||
this.$msg.success(message)
|
||||
|
||||
/* eslint-disable no-new */
|
||||
new Notification(this.$t('task.download-fail-notify'), {
|
||||
@@ -138,7 +160,7 @@
|
||||
},
|
||||
bindEngineEvents: function () {
|
||||
api.client.on('onDownloadStart', this.onDownloadStart)
|
||||
api.client.on('onDownloadPause', this.onDownloadPause)
|
||||
// api.client.on('onDownloadPause', this.onDownloadPause)
|
||||
api.client.on('onDownloadStop', this.onDownloadStop)
|
||||
api.client.on('onDownloadComplete', this.onDownloadComplete)
|
||||
api.client.on('onDownloadError', this.onDownloadError)
|
||||
@@ -146,7 +168,7 @@
|
||||
},
|
||||
unbindEngineEvents: function () {
|
||||
api.client.removeListener('onDownloadStart', this.onDownloadStart)
|
||||
api.client.removeListener('onDownloadPause', this.onDownloadPause)
|
||||
// api.client.removeListener('onDownloadPause', this.onDownloadPause)
|
||||
api.client.removeListener('onDownloadStop', this.onDownloadStop)
|
||||
api.client.removeListener('onDownloadComplete', this.onDownloadComplete)
|
||||
api.client.removeListener('onDownloadError', this.onDownloadError)
|
||||
@@ -172,6 +194,7 @@
|
||||
},
|
||||
created: function () {
|
||||
this.$store.dispatch('app/fetchEngineInfo')
|
||||
this.$store.dispatch('app/fetchEngineOptions')
|
||||
|
||||
this.startPolling()
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="title-bar">
|
||||
<div class="title-bar-dragger"></div>
|
||||
<ul v-if="showActions" class="window-actions">
|
||||
<li @click="handleMinimize">
|
||||
<mo-icon name="win-minimize" width="12" height="12" />
|
||||
@@ -50,19 +51,41 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.title-bar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
z-index: 5000;
|
||||
.title-bar-dragger {
|
||||
flex: 1;
|
||||
user-select: none;
|
||||
-webkit-app-region: drag;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
.window-actions {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 24px;
|
||||
opacity: 0.4;
|
||||
transition: $--fade-transition;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
z-index: 5100;
|
||||
> li {
|
||||
float: left;
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
margin: 0 5px;
|
||||
&:hover {
|
||||
background-color: $--titlebar-actions-active-background;
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.window-actions {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,6 +2,7 @@ import is from 'electron-is'
|
||||
import { existsSync } from 'fs'
|
||||
import { Message } from 'element-ui'
|
||||
import {
|
||||
isMagnetTask,
|
||||
getTaskFullPath,
|
||||
bytesToSize
|
||||
} from '@shared/utils'
|
||||
@@ -40,10 +41,23 @@ export function openItem (fullPath, { errorMsg }) {
|
||||
return result
|
||||
}
|
||||
|
||||
export function moveTaskFilesToTrash (task, { pathErrorMsg, delFailMsg, delConfigFailMsg }) {
|
||||
export function moveTaskFilesToTrash (task, messages = {}) {
|
||||
/**
|
||||
* 磁力链接任务,有 bittorrent,但没有 bittorrent.info ,
|
||||
* 在没下完变成BT任务之前 path 不是一个完整路径,
|
||||
* 未避免误删所在目录,所以删除时直接返回 true
|
||||
*/
|
||||
if (isMagnetTask(task)) {
|
||||
return true
|
||||
}
|
||||
|
||||
const { pathErrorMsg, delFailMsg, delConfigFailMsg } = messages
|
||||
const { dir } = task
|
||||
const path = getTaskFullPath(task)
|
||||
if (!path && pathErrorMsg) {
|
||||
Message.error(pathErrorMsg)
|
||||
if (!path || dir === path) {
|
||||
if (pathErrorMsg) {
|
||||
Message.error(pathErrorMsg)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -66,30 +80,45 @@ export function moveTaskFilesToTrash (task, { pathErrorMsg, delFailMsg, delConfi
|
||||
}
|
||||
|
||||
export function openDownloadDock (path) {
|
||||
if (!is.macOS()) {
|
||||
return
|
||||
}
|
||||
remote.app.dock.downloadFinished(path)
|
||||
}
|
||||
|
||||
export function updateDockBadge (text) {
|
||||
if (!is.macOS()) {
|
||||
return
|
||||
}
|
||||
remote.app.dock.setBadge(text)
|
||||
}
|
||||
|
||||
export function showDownloadSpeedInDock (downloadSpeed) {
|
||||
if (is.windows()) {
|
||||
if (!is.macOS()) {
|
||||
return
|
||||
}
|
||||
const text = downloadSpeed > 0 ? bytesToSize(downloadSpeed) : ''
|
||||
const text = downloadSpeed > 0 ? `${bytesToSize(downloadSpeed)}/s` : ''
|
||||
updateDockBadge(text)
|
||||
}
|
||||
|
||||
export function addToRecentTask (task) {
|
||||
if (is.linux()) {
|
||||
return
|
||||
}
|
||||
const path = getTaskFullPath(task)
|
||||
remote.app.addRecentDocument(path)
|
||||
}
|
||||
|
||||
export function addToRecentTaskByPath (path) {
|
||||
if (is.linux()) {
|
||||
return
|
||||
}
|
||||
remote.app.addRecentDocument(path)
|
||||
}
|
||||
|
||||
export function clearRecentTasks () {
|
||||
if (is.linux()) {
|
||||
return
|
||||
}
|
||||
remote.app.clearRecentDocuments()
|
||||
}
|
||||
|
||||
@@ -85,7 +85,9 @@
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-col class="form-item-sub" :span="24">
|
||||
<el-button plain type="danger" @click="() => onFactoryResetClick()">{{ $t('preferences.factory-reset') }}</el-button>
|
||||
<el-button plain type="danger" @click="() => onFactoryResetClick()">
|
||||
{{ $t('preferences.factory-reset') }}
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -102,7 +104,7 @@
|
||||
import { mapState } from 'vuex'
|
||||
import ShowInFolder from '@/components/Native/ShowInFolder'
|
||||
import userAgentMap from '@shared/ua'
|
||||
import { getLanguage } from '@shared/locales'
|
||||
import { availableLanguages, getLanguage } from '@shared/locales'
|
||||
import { getLocaleManager } from '@/components/Locale'
|
||||
|
||||
const initialForm = (config) => {
|
||||
@@ -136,16 +138,7 @@
|
||||
form: initialForm(this.$store.state.preference.config),
|
||||
rules: {},
|
||||
color: '#c00',
|
||||
locales: [
|
||||
{
|
||||
value: 'zh-CN',
|
||||
label: '🇨🇳 简体中文'
|
||||
},
|
||||
{
|
||||
value: 'en-US',
|
||||
label: '🇺🇸 English (US)'
|
||||
}
|
||||
]
|
||||
locales: availableLanguages
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -186,8 +179,8 @@
|
||||
onFactoryResetClick () {
|
||||
this.$electron.remote.dialog.showMessageBox({
|
||||
type: 'warning',
|
||||
title: '恢复初始设置',
|
||||
message: '你确定要恢复为初始设置吗?',
|
||||
title: this.$t('preferences.factory-reset'),
|
||||
message: this.$t('preferences.factory-reset-confirm'),
|
||||
buttons: [this.$t('app.yes'), this.$t('app.no')],
|
||||
cancelId: 1
|
||||
}, (buttonIndex) => {
|
||||
@@ -218,7 +211,7 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.ua-group {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.ua-group {
|
||||
margin-top: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<ul>
|
||||
<li
|
||||
@click="() => nav('basic')"
|
||||
v-bind:class="[ current === 'basic' ? 'active' : '' ]"
|
||||
:class="[ current === 'basic' ? 'active' : '' ]"
|
||||
>
|
||||
<i class="subnav-icon">
|
||||
<mo-icon name='preference-basic' width="20" height="20" />
|
||||
@@ -13,7 +13,7 @@
|
||||
</li>
|
||||
<li
|
||||
@click="() => nav('advanced')"
|
||||
v-bind:class="[ current === 'advanced' ? 'active' : '' ]"
|
||||
:class="[ current === 'advanced' ? 'active' : '' ]"
|
||||
>
|
||||
<i class="subnav-icon">
|
||||
<mo-icon name='preference-advanced' width="20" height="20" />
|
||||
@@ -22,7 +22,7 @@
|
||||
</li>
|
||||
<li
|
||||
@click="() => nav('lab')"
|
||||
v-bind:class="[ current === 'lab' ? 'active' : '' ]"
|
||||
:class="[ current === 'lab' ? 'active' : '' ]"
|
||||
>
|
||||
<i class="subnav-icon">
|
||||
<mo-icon name='preference-lab' width="20" height="20" />
|
||||
@@ -34,7 +34,6 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import is from 'electron-is'
|
||||
import '@/components/Icons/preference-basic'
|
||||
import '@/components/Icons/preference-advanced'
|
||||
import '@/components/Icons/preference-lab'
|
||||
@@ -53,7 +52,6 @@
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isMas: is.mas,
|
||||
nav: function (category = 'basic') {
|
||||
this.$router.push({
|
||||
path: `/preference/${category}`
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<ul>
|
||||
<li
|
||||
@click="() => nav('active')"
|
||||
v-bind:class="[ current === 'active' ? 'active' : '' ]"
|
||||
:class="[ current === 'active' ? 'active' : '' ]"
|
||||
>
|
||||
<i class="subnav-icon">
|
||||
<mo-icon name="task-start" width="20" height="20" />
|
||||
@@ -13,7 +13,7 @@
|
||||
</li>
|
||||
<li
|
||||
@click="() => nav('waiting')"
|
||||
v-bind:class="[ current === 'waiting' ? 'active' : '' ]"
|
||||
:class="[ current === 'waiting' ? 'active' : '' ]"
|
||||
>
|
||||
<i class="subnav-icon">
|
||||
<mo-icon name="task-pause" width="20" height="20" />
|
||||
@@ -22,7 +22,7 @@
|
||||
</li>
|
||||
<li
|
||||
@click="() => nav('stopped')"
|
||||
v-bind:class="[ current === 'stopped' ? 'active' : '' ]"
|
||||
:class="[ current === 'stopped' ? 'active' : '' ]"
|
||||
>
|
||||
<i class="subnav-icon">
|
||||
<mo-icon name="task-stop" width="20" height="20" />
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<div v-if="showAdvanced">
|
||||
<el-form-item :label="`${$t('task.task-dir')}: `" :label-width="formLabelWidth">
|
||||
<el-form-item :label="`${$t('task.task-user-agent')}: `" :label-width="formLabelWidth">
|
||||
<el-input
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 3 }"
|
||||
@@ -156,7 +156,7 @@
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
formLabelWidth: '75px',
|
||||
formLabelWidth: '100px',
|
||||
showAdvanced: false,
|
||||
torrentName: '',
|
||||
form: {},
|
||||
@@ -227,7 +227,7 @@
|
||||
// https://github.com/ElemeFE/element/blob/master/packages/input/src/input.vue
|
||||
const { uris } = this.form
|
||||
if (uris.includes('thunder://')) {
|
||||
this.$message({
|
||||
this.$msg({
|
||||
type: 'warning',
|
||||
message: this.$t('task.thunder-link-tip'),
|
||||
duration: 6000
|
||||
@@ -318,13 +318,13 @@
|
||||
payload = this.buildUriPayload(form)
|
||||
this.$store.dispatch('task/addUri', payload)
|
||||
.catch((err) => {
|
||||
this.$message.error(err.message)
|
||||
this.$msg.error(err.message)
|
||||
})
|
||||
} else if (type === 'torrent') {
|
||||
payload = this.buildTorrentPayload(form)
|
||||
this.$store.dispatch('task/addTorrent', payload)
|
||||
.catch((err) => {
|
||||
this.$message.error(err.message)
|
||||
this.$msg.error(err.message)
|
||||
})
|
||||
} else if (type === 'metalink') {
|
||||
// @TODO addMetalink
|
||||
@@ -382,7 +382,7 @@
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
this.$message.error(err.message)
|
||||
this.$msg.error(err.message)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,8 +3,11 @@
|
||||
class="upload-torrent"
|
||||
drag
|
||||
action="/"
|
||||
:limit="1"
|
||||
:multiple="false"
|
||||
accept=".torrent"
|
||||
:on-change="handleChange"
|
||||
:on-exceed="handleExceed"
|
||||
:auto-upload="false"
|
||||
:show-file-list="false">
|
||||
<i class="upload-inbox-icon"><mo-icon name="inbox" width="24" height="24" /></i>
|
||||
@@ -19,7 +22,7 @@
|
||||
import { mapState } from 'vuex'
|
||||
import parseTorrent from 'parse-torrent'
|
||||
import '@/components/Icons/inbox'
|
||||
import { getAsBase64 } from '@shared/utils'
|
||||
import { getAsBase64, buildFileList } from '@shared/utils'
|
||||
|
||||
export default {
|
||||
name: 'mo-select-torrent',
|
||||
@@ -35,11 +38,18 @@
|
||||
computed: {
|
||||
...mapState('preference', {
|
||||
config: state => state.config
|
||||
}),
|
||||
...mapState('app', {
|
||||
torrents: state => state.addTaskTorrents
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
handleChange (file, fileList) {
|
||||
console.log('file===>', file)
|
||||
watch: {
|
||||
torrents (fileList) {
|
||||
const file = fileList[0]
|
||||
if (fileList.length === 0) {
|
||||
this.name = ''
|
||||
return
|
||||
}
|
||||
if (!file.raw) {
|
||||
return
|
||||
}
|
||||
@@ -54,6 +64,15 @@
|
||||
this.$emit('change', torrent, file, fileList)
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleChange (file, fileList) {
|
||||
this.$store.dispatch('app/addTaskAddTorrents', { fileList })
|
||||
},
|
||||
handleExceed (files) {
|
||||
const fileList = buildFileList(files[0])
|
||||
this.$store.dispatch('app/addTaskAddTorrents', { fileList })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
import '@/components/Icons/purge'
|
||||
import '@/components/Icons/more'
|
||||
import {
|
||||
getTaskName,
|
||||
bytesToSize,
|
||||
timeFormat
|
||||
} from '@shared/utils'
|
||||
@@ -70,7 +69,6 @@
|
||||
timeFormat
|
||||
},
|
||||
methods: {
|
||||
getTaskName,
|
||||
refreshSpin: function () {
|
||||
this.t && clearTimeout(this.t)
|
||||
|
||||
@@ -86,33 +84,33 @@
|
||||
onResumeAllClick: function () {
|
||||
this.$store.dispatch('task/resumeAllTask')
|
||||
.then(() => {
|
||||
this.$message.success(this.$t('task.resume-all-task-success'))
|
||||
this.$msg.success(this.$t('task.resume-all-task-success'))
|
||||
})
|
||||
.catch(({ code }) => {
|
||||
if (code === 1) {
|
||||
this.$message.error(this.$t('task.resume-all-task-fail'))
|
||||
this.$msg.error(this.$t('task.resume-all-task-fail'))
|
||||
}
|
||||
})
|
||||
},
|
||||
onPauseAllClick: function () {
|
||||
this.$store.dispatch('task/pauseAllTask')
|
||||
.then(() => {
|
||||
this.$message.success(this.$t('task.pause-all-task-success'))
|
||||
this.$msg.success(this.$t('task.pause-all-task-success'))
|
||||
})
|
||||
.catch(({ code }) => {
|
||||
if (code === 1) {
|
||||
this.$message.error(this.$t('task.pause-all-task-fail'))
|
||||
this.$msg.error(this.$t('task.pause-all-task-fail'))
|
||||
}
|
||||
})
|
||||
},
|
||||
onPurgeRecordClick: function () {
|
||||
this.$store.dispatch('task/purgeTaskRecord')
|
||||
.then(() => {
|
||||
this.$message.success(this.$t('task.purge-record-success'))
|
||||
this.$msg.success(this.$t('task.purge-record-success'))
|
||||
})
|
||||
.catch(({ code }) => {
|
||||
if (code === 1) {
|
||||
this.$message.error(this.$t('task.purge-record-fail'))
|
||||
this.$msg.error(this.$t('task.purge-record-fail'))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<li :key="task.gid" class="task-item" v-on:dblclick="onDbClick">
|
||||
<div class="task-name" :title="taskName">
|
||||
<span>{{ taskName }}</span>
|
||||
<div class="task-name" :title="taskFullName">
|
||||
<span>{{ taskFullName }}</span>
|
||||
</div>
|
||||
<mo-task-item-actions mode="LIST" :task="task" />
|
||||
<div class="task-progress">
|
||||
@@ -68,8 +68,16 @@
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
taskFullName: function () {
|
||||
return getTaskName(this.task, {
|
||||
defaultName: this.$t('task.get-task-name'),
|
||||
maxLen: -1
|
||||
})
|
||||
},
|
||||
taskName: function () {
|
||||
return getTaskName(this.task, this.$t('task.get-task-name'))
|
||||
return getTaskName(this.task, {
|
||||
defaultName: this.$t('task.get-task-name')
|
||||
})
|
||||
},
|
||||
remaining: function () {
|
||||
const { totalLength, completedLength, downloadSpeed } = this.task
|
||||
@@ -81,7 +89,6 @@
|
||||
timeFormat
|
||||
},
|
||||
methods: {
|
||||
getTaskName,
|
||||
onDbClick () {
|
||||
const { status } = this.task
|
||||
if (status === 'complete') {
|
||||
@@ -92,7 +99,7 @@
|
||||
},
|
||||
openTask () {
|
||||
const { taskName } = this
|
||||
this.$message.info(this.$t('task.opening-task-message', { taskName }))
|
||||
this.$msg.info(this.$t('task.opening-task-message', { taskName }))
|
||||
const fullPath = getTaskFullPath(this.task)
|
||||
openItem(fullPath, {
|
||||
errorMsg: this.$t('task.file-not-exist')
|
||||
@@ -126,6 +133,7 @@
|
||||
color: #505753;
|
||||
margin-bottom: 32px;
|
||||
margin-right: 240px;
|
||||
word-break: break-all;
|
||||
&> span {
|
||||
font-size: 14px;
|
||||
line-height: 26px;
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
<script>
|
||||
import is from 'electron-is'
|
||||
import clipboard from 'clipboard-polyfill'
|
||||
import * as clipboard from 'clipboard-polyfill'
|
||||
import '@/components/Icons/task-start-line'
|
||||
import '@/components/Icons/task-pause-line'
|
||||
import '@/components/Icons/delete'
|
||||
@@ -89,13 +89,13 @@
|
||||
if (isRemoveWithFiles) {
|
||||
this.deleteTaskFiles(task)
|
||||
}
|
||||
this.$message.success(this.$t('task.delete-task-success', {
|
||||
this.$msg.success(this.$t('task.delete-task-success', {
|
||||
taskName: this.taskName
|
||||
}))
|
||||
})
|
||||
.catch(({ code }) => {
|
||||
if (code === 1) {
|
||||
this.$message.error(this.$t('task.delete-task-fail', {
|
||||
this.$msg.error(this.$t('task.delete-task-fail', {
|
||||
taskName: this.taskName
|
||||
}))
|
||||
}
|
||||
@@ -107,13 +107,13 @@
|
||||
if (isRemoveWithFiles) {
|
||||
this.deleteTaskFiles(task)
|
||||
}
|
||||
this.$message.success(this.$t('task.remove-record-success', {
|
||||
this.$msg.success(this.$t('task.remove-record-success', {
|
||||
taskName: this.taskName
|
||||
}))
|
||||
})
|
||||
.catch(({ code }) => {
|
||||
if (code === 1) {
|
||||
this.$message.error(this.$t('task.remove-record-fail', {
|
||||
this.$msg.error(this.$t('task.remove-record-fail', {
|
||||
taskName: this.taskName
|
||||
}))
|
||||
}
|
||||
@@ -123,19 +123,19 @@
|
||||
this.$store.dispatch('task/resumeTask', this.task)
|
||||
.catch(({ code }) => {
|
||||
if (code === 1) {
|
||||
this.$message.error(this.$t('task.resume-task-fail', {
|
||||
this.$msg.error(this.$t('task.resume-task-fail', {
|
||||
taskName: this.taskName
|
||||
}))
|
||||
}
|
||||
})
|
||||
},
|
||||
onPauseClick: function () {
|
||||
const { taskName } = this
|
||||
this.$msg.info(this.$t('task.download-pause-message', { taskName }))
|
||||
this.$store.dispatch('task/pauseTask', this.task)
|
||||
.catch(({ code }) => {
|
||||
if (code === 1) {
|
||||
this.$message.error(this.$t('task.pause-task-fail', {
|
||||
taskName: this.taskName
|
||||
}))
|
||||
this.$msg.error(this.$t('task.pause-task-fail', { taskName }))
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -177,10 +177,14 @@
|
||||
})
|
||||
},
|
||||
onLinkClick: function () {
|
||||
const uri = getTaskUri(this.task)
|
||||
clipboard.writeText(uri)
|
||||
.then(() => {
|
||||
this.$message.success(this.$t('task.copy-link-success'))
|
||||
this.$store.dispatch('app/fetchEngineOptions')
|
||||
.then((data) => {
|
||||
const { btTracker } = data
|
||||
const uri = getTaskUri(this.task, btTracker)
|
||||
clipboard.writeText(uri)
|
||||
.then(() => {
|
||||
this.$msg.success(this.$t('task.copy-link-success'))
|
||||
})
|
||||
})
|
||||
},
|
||||
onInfoClick: function () {
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
:before-close="handleClose"
|
||||
@closed="handleClosed"
|
||||
>
|
||||
<div class="task-name" :title="taskName">
|
||||
<span>{{ taskName }}</span>
|
||||
<div class="task-name" :title="taskFullName">
|
||||
<span>{{ taskFullName }}</span>
|
||||
</div>
|
||||
<mo-task-item-actions mode="ITEM" :task="task" />
|
||||
<div class="task-progress">
|
||||
@@ -78,13 +78,20 @@
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
taskFullName: function () {
|
||||
return getTaskName(this.task, {
|
||||
defaultName: this.$t('task.get-task-name'),
|
||||
maxLen: -1
|
||||
})
|
||||
},
|
||||
taskName: function () {
|
||||
return getTaskName(this.task, this.$t('task.get-task-name'))
|
||||
return getTaskName(this.task, {
|
||||
defaultName: this.$t('task.get-task-name'),
|
||||
maxLen: 32
|
||||
})
|
||||
},
|
||||
dialogTitle: function () {
|
||||
const len = this.taskName.length
|
||||
let title = len > 40 ? this.taskName.substr(0, 40) + '...' : this.taskName
|
||||
return this.$t('task.task-info-dialog-title', { title })
|
||||
return this.$t('task.task-info-dialog-title', { title: this.taskName })
|
||||
},
|
||||
remaining: function () {
|
||||
const { totalLength, completedLength, downloadSpeed } = this.task
|
||||
@@ -96,7 +103,6 @@
|
||||
timeFormat
|
||||
},
|
||||
methods: {
|
||||
getTaskName,
|
||||
handleClose (done) {
|
||||
this.$store.dispatch('task/hideTaskItemInfoDialog')
|
||||
},
|
||||
|
||||
@@ -12,12 +12,6 @@
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import TaskItem from './TaskItem'
|
||||
import {
|
||||
getTaskName,
|
||||
bytesToSize,
|
||||
timeRemaining,
|
||||
timeFormat
|
||||
} from '@shared/utils'
|
||||
|
||||
export default {
|
||||
name: 'mo-task-list',
|
||||
@@ -30,10 +24,6 @@
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
getTaskName,
|
||||
bytesToSize,
|
||||
timeRemaining,
|
||||
timeFormat
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -21,26 +21,6 @@ img {
|
||||
@include clearfix();
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
user-select: none;
|
||||
-webkit-app-region: drag;
|
||||
-webkit-user-select: none;
|
||||
z-index: 5000;
|
||||
&> .window-actions {
|
||||
opacity: 0.4;
|
||||
transition: $--fade-transition;
|
||||
}
|
||||
&:hover {
|
||||
.window-actions {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#app,
|
||||
#container {
|
||||
height: 100%;
|
||||
@@ -89,6 +69,11 @@ img {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.el-message__content {
|
||||
line-height: 18px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.tab-title-dialog {
|
||||
.el-dialog__header {
|
||||
padding: 0 20px;
|
||||
@@ -104,6 +89,7 @@ img {
|
||||
.el-form-item--mini .el-form-item__info {
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.el-form-item__info {
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
|
||||
@@ -2,7 +2,7 @@ import is from 'electron-is'
|
||||
import Vue from 'vue'
|
||||
import VueI18Next from '@panter/vue-i18next'
|
||||
import { sync } from 'vuex-router-sync'
|
||||
import Element, { Loading } from 'element-ui'
|
||||
import Element, { Loading, Message } from 'element-ui'
|
||||
import axios from 'axios'
|
||||
import 'svg-innerhtml'
|
||||
|
||||
@@ -11,6 +11,8 @@ import router from '@/router'
|
||||
import store from '@/store'
|
||||
import { getLocaleManager } from '@/components/Locale'
|
||||
import Icon from '@/components/Icons/Icon'
|
||||
import Msg from '@/components/Msg'
|
||||
|
||||
import '@/components/Theme/Index.scss'
|
||||
|
||||
function init (config) {
|
||||
@@ -31,6 +33,9 @@ function init (config) {
|
||||
size: 'mini',
|
||||
i18n: (key, value) => i18n.t(key, value)
|
||||
})
|
||||
Vue.use(Msg, Message, {
|
||||
showClose: true
|
||||
})
|
||||
|
||||
const loading = Loading.service({
|
||||
fullscreen: true,
|
||||
|
||||
@@ -12,6 +12,7 @@ const state = {
|
||||
version: '',
|
||||
enabledFeatures: []
|
||||
},
|
||||
engineOptions: {},
|
||||
interval: BASE_INTERVAL,
|
||||
stat: {
|
||||
downloadSpeed: 0,
|
||||
@@ -21,7 +22,8 @@ const state = {
|
||||
numWaiting: 0
|
||||
},
|
||||
addTaskVisible: false,
|
||||
addTaskType: 'uri'
|
||||
addTaskType: 'uri',
|
||||
addTaskTorrents: []
|
||||
}
|
||||
|
||||
const getters = {
|
||||
@@ -34,6 +36,9 @@ const mutations = {
|
||||
UPDATE_ENGINE_INFO (state, engineInfo) {
|
||||
state.engineInfo = { ...state.engineInfo, ...engineInfo }
|
||||
},
|
||||
UPDATE_ENGINE_OPTIONS (state, engineOptions) {
|
||||
state.engineOptions = { ...state.engineOptions, ...engineOptions }
|
||||
},
|
||||
UPDATE_GLOBAL_STAT (state, stat) {
|
||||
state.stat = stat
|
||||
},
|
||||
@@ -43,6 +48,9 @@ const mutations = {
|
||||
CHANGE_ADD_TASK_TYPE (state, taskType) {
|
||||
state.addTaskType = taskType
|
||||
},
|
||||
CHANGE_ADD_TASK_TORRENTS (state, fileList) {
|
||||
state.addTaskTorrents = [...fileList]
|
||||
},
|
||||
UPDATE_INTERVAL (state, millisecond) {
|
||||
let interval = millisecond
|
||||
if (millisecond > MAX_INTERVAL) {
|
||||
@@ -81,6 +89,15 @@ const actions = {
|
||||
commit('UPDATE_ENGINE_INFO', data)
|
||||
})
|
||||
},
|
||||
fetchEngineOptions ({ commit }) {
|
||||
return new Promise((resolve) => {
|
||||
api.getGlobalOption()
|
||||
.then((data) => {
|
||||
commit('UPDATE_ENGINE_OPTIONS', data)
|
||||
resolve(data)
|
||||
})
|
||||
})
|
||||
},
|
||||
fetchGlobalStat ({ commit, dispatch }) {
|
||||
api.getGlobalStat()
|
||||
.then((data) => {
|
||||
@@ -121,10 +138,14 @@ const actions = {
|
||||
},
|
||||
hideAddTaskDialog ({ commit }) {
|
||||
commit('CHANGE_ADD_TASK_VISIBLE', false)
|
||||
commit('CHANGE_ADD_TASK_TORRENTS', [])
|
||||
},
|
||||
changeAddTaskType ({ commit }, taskType) {
|
||||
commit('CHANGE_ADD_TASK_TYPE', taskType)
|
||||
},
|
||||
addTaskAddTorrents ({ commit }, { fileList }) {
|
||||
commit('CHANGE_ADD_TASK_TORRENTS', fileList)
|
||||
},
|
||||
updateInterval ({ commit }, millisecond) {
|
||||
commit('UPDATE_INTERVAL', millisecond)
|
||||
},
|
||||
|
||||
@@ -31,13 +31,13 @@ const actions = {
|
||||
dispatch('fetchList')
|
||||
},
|
||||
fetchList ({ state, commit }) {
|
||||
api.fetchTaskList({ type: state.currentList })
|
||||
return api.fetchTaskList({ type: state.currentList })
|
||||
.then((data) => {
|
||||
commit('UPDATE_TASK_LIST', data)
|
||||
})
|
||||
},
|
||||
fetchItem ({ dispatch }, gid) {
|
||||
api.fetchTaskItem({ gid })
|
||||
return api.fetchTaskItem({ gid })
|
||||
.then((data) => {
|
||||
dispatch('updateCurrentTaskItem', data)
|
||||
})
|
||||
@@ -75,13 +75,16 @@ const actions = {
|
||||
},
|
||||
removeTask ({ dispatch }, task) {
|
||||
const { gid } = task
|
||||
return api.removeTask({ gid })
|
||||
.catch(() => {
|
||||
return api.forceRemoveTask({ gid })
|
||||
return api.forcePauseTask({ gid })
|
||||
.catch((e) => {
|
||||
console.log(`[Motrix] removeTask.forcePauseTask#[${gid}] fail`, e.message)
|
||||
})
|
||||
.finally(() => {
|
||||
dispatch('fetchList')
|
||||
dispatch('saveSession')
|
||||
return api.removeTask({ gid })
|
||||
.finally(() => {
|
||||
dispatch('fetchList')
|
||||
dispatch('saveSession')
|
||||
})
|
||||
})
|
||||
},
|
||||
pauseTask ({ dispatch }, task) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"cmd-n": "application:new-task",
|
||||
"cmd-shift-n": "application:new-bt-task",
|
||||
"cmd-o": "application:open-file",
|
||||
"cmd-,": "application:preferences",
|
||||
"cmd-shift-p": "application:pause-all-task",
|
||||
"cmd-shift-r": "application:resume-all-task"
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import i18next from 'i18next'
|
||||
import { getLanguage } from '@shared/locales'
|
||||
|
||||
export default class LocaleManager {
|
||||
constructor (options = {}) {
|
||||
this.options = options
|
||||
|
||||
i18next.init({
|
||||
fallbackLng: 'en-US',
|
||||
resources: options.resources
|
||||
})
|
||||
}
|
||||
|
||||
changeLanguage (lng) {
|
||||
return i18next.changeLanguage(lng)
|
||||
}
|
||||
|
||||
changeLanguageByLocale (locale) {
|
||||
const lng = getLanguage(locale)
|
||||
return this.changeLanguage(lng)
|
||||
}
|
||||
|
||||
getI18n () {
|
||||
return i18next
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,61 @@
|
||||
import eleLocaleDe from 'element-ui/lib/locale/lang/de'
|
||||
import eleLocaleEn from 'element-ui/lib/locale/lang/en'
|
||||
import eleLocaleFr from 'element-ui/lib/locale/lang/fr'
|
||||
import eleLocalePtBR from 'element-ui/lib/locale/lang/pt-br'
|
||||
import eleLocaleTr from 'element-ui/lib/locale/lang/tr-TR'
|
||||
import eleLocaleZhCN from 'element-ui/lib/locale/lang/zh-CN'
|
||||
import eleLocaleZhTW from 'element-ui/lib/locale/lang/zh-TW'
|
||||
import appLocaleDe from '@shared/locales/de'
|
||||
import appLocaleEnUS from '@shared/locales/en-US'
|
||||
import appLocaleFr from '@shared/locales/fr'
|
||||
import appLocalePtBR from '@shared/locales/pt-BR'
|
||||
import appLocaleTr from '@shared/locales/tr'
|
||||
import appLocaleZhCN from '@shared/locales/zh-CN'
|
||||
import appLocaleZhTW from '@shared/locales/zh-TW'
|
||||
|
||||
// Please keep the locale key in alphabetical order.
|
||||
const resources = {
|
||||
'de': {
|
||||
translation: {
|
||||
...eleLocaleDe,
|
||||
...appLocaleDe
|
||||
}
|
||||
},
|
||||
'en-US': {
|
||||
translation: {
|
||||
...eleLocaleEn,
|
||||
...appLocaleEnUS
|
||||
}
|
||||
},
|
||||
'fr': {
|
||||
translation: {
|
||||
...eleLocaleFr,
|
||||
...appLocaleFr
|
||||
}
|
||||
},
|
||||
'pt-BR': {
|
||||
translation: {
|
||||
...eleLocalePtBR,
|
||||
...appLocalePtBR
|
||||
}
|
||||
},
|
||||
'tr': {
|
||||
translation: {
|
||||
...eleLocaleTr,
|
||||
...appLocaleTr
|
||||
}
|
||||
},
|
||||
'zh-CN': {
|
||||
translation: {
|
||||
...eleLocaleZhCN,
|
||||
...appLocaleZhCN
|
||||
}
|
||||
},
|
||||
'zh-TW': {
|
||||
translation: {
|
||||
...eleLocaleZhTW,
|
||||
...appLocaleZhTW
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,47 @@
|
||||
import appLocaleDeDE from '@shared/locales/de'
|
||||
import appLocaleEnUS from '@shared/locales/en-US'
|
||||
import appLocaleFrFR from '@shared/locales/fr'
|
||||
import appLocalePtBr from '@shared/locales/pt-BR'
|
||||
import appLocaleTrTR from '@shared/locales/tr'
|
||||
import appLocaleZhCN from '@shared/locales/zh-CN'
|
||||
import appLocaleZhTW from '@shared/locales/zh-TW'
|
||||
|
||||
// Please keep the locale key in alphabetical order.
|
||||
const resources = {
|
||||
'de': {
|
||||
translation: {
|
||||
...appLocaleDeDE
|
||||
}
|
||||
},
|
||||
'en-US': {
|
||||
translation: {
|
||||
...appLocaleEnUS
|
||||
}
|
||||
},
|
||||
'fr': {
|
||||
translation: {
|
||||
...appLocaleFrFR
|
||||
}
|
||||
},
|
||||
'pt-BR': {
|
||||
translation: {
|
||||
...appLocalePtBr
|
||||
}
|
||||
},
|
||||
'tr': {
|
||||
translation: {
|
||||
...appLocaleTrTR
|
||||
}
|
||||
},
|
||||
'zh-CN': {
|
||||
translation: {
|
||||
...appLocaleZhCN
|
||||
}
|
||||
},
|
||||
'zh-TW': {
|
||||
translation: {
|
||||
...appLocaleZhTW
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
export default {
|
||||
'engine-version': 'Engine Version',
|
||||
'about': 'Über',
|
||||
'release': 'Versionen',
|
||||
'support': 'Unterstützung anfordern'
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
export default {
|
||||
'task-list': 'Aufgabenliste',
|
||||
'add-task': 'Aufgabe hinzufügen',
|
||||
'about': 'Über Motrix',
|
||||
'preferences': 'Präferenzen...',
|
||||
'check-for-updates': 'Nach Updates suchen...',
|
||||
'check-for-updates-title': 'Nach Updates suchen',
|
||||
'update-available-message': 'Eine neue Version von Motrix ist verfügbar, jetzt aktualisieren?',
|
||||
'update-not-available-message': 'Sie sind auf dem neuesten Stand!',
|
||||
'update-downloaded-message': 'Bereit zur Installation...',
|
||||
'update-error-message': 'Aktualisierungsfehler',
|
||||
'engine-damaged-message': 'Der Motor ist beschädigt, bitte neu installieren : (',
|
||||
'engine-missing-message': 'Der Motor fehlt, bitte neu installieren : (',
|
||||
'system-error-title': 'Systemfehler',
|
||||
'system-error-message': 'Die Anwendung konnte nicht gestartet werden: {{message}}',
|
||||
'hide': 'Motrix verbergen',
|
||||
'hide-others': 'Andere verbergen',
|
||||
'unhide': 'Alles anzeigen',
|
||||
'show': 'Motrix anzeigen',
|
||||
'quit': 'Motrix beenden',
|
||||
'under-development-message': 'Entschuldigung, diese Funktion befindet sich in der Entwicklung...',
|
||||
'yes': 'Ja',
|
||||
'no': 'Nein',
|
||||
'cancel': 'Abbrechen',
|
||||
'submit': 'Übernehmen',
|
||||
'gt1d': '> 1 Tag',
|
||||
'hour': 'h',
|
||||
'minute': 'm',
|
||||
'second': 's'
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export default {
|
||||
'undo': 'Rückgängig',
|
||||
'redo': 'Wiederholen',
|
||||
'cut': 'Ausschneiden',
|
||||
'copy': 'Kopieren',
|
||||
'paste': 'Einfügen',
|
||||
'delete': 'Löschen',
|
||||
'select-all': 'Alles auswählen'
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export default {
|
||||
'official-website': 'Motrix Website',
|
||||
'manual': 'Handbuch',
|
||||
'release-notes': 'Versionshinweise...',
|
||||
'report-problem': 'Problem melden',
|
||||
'toggle-dev-tools': 'Entwicklerwerkzeuge umschalten'
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import about from './about'
|
||||
import app from './app'
|
||||
import edit from './edit'
|
||||
import help from './help'
|
||||
import menu from './menu'
|
||||
import preferences from './preferences'
|
||||
import subnav from './subnav'
|
||||
import task from './task'
|
||||
import window from './window'
|
||||
|
||||
export default {
|
||||
about,
|
||||
app,
|
||||
edit,
|
||||
help,
|
||||
menu,
|
||||
preferences,
|
||||
subnav,
|
||||
task,
|
||||
window
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export default {
|
||||
'app': 'Motrix',
|
||||
'file': 'Datei',
|
||||
'task': 'Aufgabe',
|
||||
'edit': 'Bearbeiten',
|
||||
'window': 'Fenster',
|
||||
'help': 'Hilfe'
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
export default {
|
||||
'basic': 'Standard',
|
||||
'advanced': 'Erweitert',
|
||||
'lab': 'Experimentell',
|
||||
'save': 'Speichern & übernehmen',
|
||||
'discard': 'Verwerfen',
|
||||
'startup': 'Startup',
|
||||
'auto-resume-all': 'Alle nicht abgeschlossenen Aufgaben automatisch fortsetzen',
|
||||
'default-dir': 'Standard Speicherort',
|
||||
'mas-default-dir-tip': 'Aufgrund der Einschränkungen durch Sandbox-Berechtigungen im App Store wird der Download Ordner als Standard empfohlen',
|
||||
'task-manage': 'Aufgaben verwalten',
|
||||
'max-concurrent-downloads': 'Maximal aktive Aufgaben',
|
||||
'max-connection-per-server': 'Maximale Verbindungen pro Server',
|
||||
'new-task-show-downloading': 'Nach hinzufügen einer Aufgabe zu aktiven Downloads wechseln',
|
||||
'continue': 'HTTPS/FTP Downloads fortsetzen wenn bereits angefangen',
|
||||
'task-completed-notify': 'Benachrichtigung nach abgeschlossenen Download anzeigen',
|
||||
'auto-purge-record': 'Download Protokoll beim Schließen der App löschen',
|
||||
'ui': 'UI',
|
||||
'language': 'Sprache',
|
||||
'change-language': 'Sprache ändern',
|
||||
'hide-app-menu': 'App Menü ausblenden (nur auf Windows & Linux)',
|
||||
'proxy': 'Proxy',
|
||||
'use-proxy': 'Proxy aktivieren',
|
||||
'developer': 'Entwickler',
|
||||
'mock-user-agent': 'User-Agent simulieren',
|
||||
'app-log-path': 'Appprotokollpfad',
|
||||
'download-session-path': 'Downloadsitzungspfad',
|
||||
'factory-reset': 'Werkseinstellungen',
|
||||
'factory-reset-confirm': 'Sollen die Einstellungen auf die Werkseinstellungen unwiderruflich zurückgesetzt werden?',
|
||||
'lab-warning': '⚠️ Die Aktivierung von experimentellen Funktionen kann zu App-Abstürzen oder Datenverlust führen!',
|
||||
'download-protocol': 'Protokoll',
|
||||
'support-more-download-protocols': 'Erweiterte Protokollunterstützung aktivieren',
|
||||
'browser-extensions': 'Erweiterungen',
|
||||
'baidu-exporter': 'Baidu Exporter',
|
||||
'browser-extensions-tip': 'Von der Community bereitgestellt, ',
|
||||
'baidu-exporter-help': 'mehr über die Verwendung zu erfahren'
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export default {
|
||||
'task-list': 'Aufgaben',
|
||||
'preferences': 'Präferenzen'
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
export default {
|
||||
'active': 'Aktiv',
|
||||
'waiting': 'Warteschlange',
|
||||
'stopped': 'Gestoppt',
|
||||
'new-task': 'Neue Aufgabe',
|
||||
'new-bt-task': 'Neue BT Aufgabe',
|
||||
'open-file': 'Torrent-Datei öffnen...',
|
||||
'uri-task': 'URL',
|
||||
'torrent-task': 'Torrent',
|
||||
'uri-task-tip': 'Eine Download URL pro Zeile (magnet wird unterstützt)',
|
||||
'thunder-link-tip': 'Tipp: Thunder Links werden möglicherweise nach dem dekodieren nicht heruntergeladen',
|
||||
'task-name': 'Aufgaben Name',
|
||||
'task-out': 'Umbenennen',
|
||||
'task-out-tip': 'Optional, unterstützt nur Einzelaufgaben',
|
||||
'task-split': 'Splits',
|
||||
'task-dir': 'Ordner',
|
||||
'pause-task': 'Aufgabe pausieren',
|
||||
'task-ua': 'UA',
|
||||
'task-user-agent': 'User-Agent',
|
||||
'task-referer': 'Referer',
|
||||
'task-cookie': 'Cookie',
|
||||
'navigate-to-downloading': 'Navigiere zu aktive Downloads',
|
||||
'show-advanced-options': 'Erweiterte Optionen',
|
||||
'copyright-warning': 'Copyright Warnung',
|
||||
'copyright-warning-message': 'Die Datei, die Sie herunterladen möchten, könnte unter Copyright stehen. Bitte überprüfen Sie ob Sie in Besitz der notwendigen Lizenz sind.',
|
||||
'copyright-yes': 'Ja, Ich habe',
|
||||
'copyright-no': 'Nein',
|
||||
'copyright-error-message': 'Aufgabe konnte Aufgrund von Copyright Problemen nicht hinzugefügt werden',
|
||||
'pause-task-success': 'Aufgabe "{{taskName}}" erfolgreich pausiert',
|
||||
'pause-task-fail': 'Aufgabe "{{taskName}}" pausieren fehlgeschlagen',
|
||||
'resume-task': 'Aufgabe fortsetzen',
|
||||
'resume-task-success': 'Aufgabe "{{taskName}}" erfolgreich fortgesetzt',
|
||||
'resume-task-fail': 'Aufgabe "{{taskName}}" fortsetzen ist fehlgschlagen',
|
||||
'delete-task': 'Aufgabe löschen',
|
||||
'delete-selected-tasks': 'Ausgewählte Aufgaben löschen',
|
||||
'delete-task-confirm': 'Den Download von "{{taskName}}" unwiederruflich löschen?',
|
||||
'delete-task-label': 'Datei auch löschen',
|
||||
'delete-task-success': 'Aufgabe "{{taskName}}" erfolgreich gelöscht',
|
||||
'delete-task-fail': 'Aufgabe "{{taskName}}" löschen fehlgeschlagen',
|
||||
'remove-task-file-fail': 'Aufgaben Datei löschen fehlgeschlagen, bitte manuell löschen',
|
||||
'remove-task-config-file-fail': 'Aufgaben Konfigurationsdatei löschen fehlgeschlagen, bitte manuell löschen',
|
||||
'move-task-up': 'Aufgabe nach oben verschieben',
|
||||
'move-task-down': 'Aufgabe nach unten verschieben',
|
||||
'pause-all-task': 'Alle Aufgaben pausieren',
|
||||
'pause-all-task-success': 'Alle Aufgaben erfolgreich pausiert',
|
||||
'pause-all-task-fail': 'Die Aufgaben konnten nicht pausiert werden',
|
||||
'resume-all-task': 'Alle Aufgaben fortsetzen',
|
||||
'resume-all-task-success': 'Alle Aufgaben erfolgreich fortgesetzt',
|
||||
'resume-all-task-fail': 'Fortsetzen aller Aufgaben fehlgeschlagen',
|
||||
'clear-recent-tasks': 'Letzte Aufgaben entfernen',
|
||||
'purge-record': 'Aufgaben Protokoll löschen',
|
||||
'purge-record-success': 'Aufgabenprotokoll erfolgreich gelöscht',
|
||||
'purge-record-fail': 'Aufgabenprotokoll konnte nicht gelöscht werden',
|
||||
'refresh-list': 'Aufgabenliste aktualisieren',
|
||||
'no-task': 'Keine Downloads aktiv',
|
||||
'copy-link': 'Link kopieren',
|
||||
'copy-link-success': 'Link erfolgreich kopiert',
|
||||
'remove-record': 'Aufgaben Aufzeichnung löschen',
|
||||
'remove-record-confirm': 'Soll die Aufzeichnung von "{{taskName}}" gelöscht werden?',
|
||||
'remove-record-label': 'Datei auch löschen',
|
||||
'remove-record-success': 'Aufzeichnung von "{{taskName}}" erfolgreich gelöscht',
|
||||
'remove-record-fail': 'Aufzeichnung von "{{taskName}}" konnte nicht gelöscht werden',
|
||||
'show-in-folder': 'Aufgabe in Ordner anzeigen',
|
||||
'file-not-exist': 'Datei existiert nicht oder wurde gelöscht',
|
||||
'file-path-error': 'Dateipfadfehler',
|
||||
'opening-task-message': 'Öffne "{{taskName}}" ...',
|
||||
'get-task-name': 'Aufgabenbezeichnung bekommen...',
|
||||
'remaining-prefix': 'Verbleibend',
|
||||
'select-torrent': 'Torrent mit Drag & Drop hinzufügen, oder klicken um auszuwählen',
|
||||
'task-info-dialog-title': '{{title}} Details',
|
||||
'download-start-message': 'Starte Download von {{taskName}}',
|
||||
'download-pause-message': 'Pausiere Download von {{taskName}}',
|
||||
'download-stop-message': 'Download von {{taskName}} gestoppt',
|
||||
'download-error-message': 'Fehler beim Download von {{taskName}} aufgetreten',
|
||||
'download-complete-message': 'Download von {{taskName}} abgeschlossen',
|
||||
'download-complete-notify': 'Download abgeschlossen',
|
||||
'download-fail-message': 'Download von {{taskName}} fehlgeschlagen',
|
||||
'download-fail-notify': 'Download fehlgeschlagen'
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export default {
|
||||
'reload': 'Neu laden',
|
||||
'close': 'Schließen',
|
||||
'minimize': 'Minimieren',
|
||||
'zoom': 'Zoomen',
|
||||
'toggle-fullscreen': 'Vollbildmodus aktivieren',
|
||||
'front': 'Alles in den Vordergrund bringen'
|
||||
}
|
||||
@@ -4,9 +4,19 @@ export default {
|
||||
'about': 'About Motrix',
|
||||
'preferences': 'Preferences...',
|
||||
'check-for-updates': 'Check for Updates...',
|
||||
'check-for-updates-title': 'Check for Updates',
|
||||
'update-available-message': 'A new version of Motrix is available, update now?',
|
||||
'update-not-available-message': 'You are up-to-date!',
|
||||
'update-downloaded-message': 'Ready to install...',
|
||||
'update-error-message': 'Update Error',
|
||||
'engine-damaged-message': 'The engine is damaged, please reinstall : (',
|
||||
'engine-missing-message': 'The engine is missing, please reinstall : (',
|
||||
'system-error-title': 'System Error',
|
||||
'system-error-message': 'Application startup failed: {{message}}',
|
||||
'hide': 'Hide Motrix',
|
||||
'hide-others': 'Hide Others',
|
||||
'unhide': 'Show All',
|
||||
'show': 'Show Motrix',
|
||||
'quit': 'Quit Motrix',
|
||||
'under-development-message': 'Sorry, this feature is under development...',
|
||||
'yes': 'Yes',
|
||||
@@ -14,7 +24,7 @@ export default {
|
||||
'cancel': 'Cancel',
|
||||
'submit': 'Submit',
|
||||
'gt1d': '> 1 day',
|
||||
'hour': 'H',
|
||||
'hour': 'h',
|
||||
'minute': 'm',
|
||||
'second': 's'
|
||||
}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import about from './about'
|
||||
import app from './app'
|
||||
// import edit from './edit'
|
||||
// import help from './help'
|
||||
// import menu from './menu'
|
||||
import edit from './edit'
|
||||
import help from './help'
|
||||
import menu from './menu'
|
||||
import preferences from './preferences'
|
||||
import subnav from './subnav'
|
||||
import task from './task'
|
||||
// import window from './window'
|
||||
import window from './window'
|
||||
|
||||
export default {
|
||||
about,
|
||||
app,
|
||||
// edit,
|
||||
// help,
|
||||
// menu,
|
||||
edit,
|
||||
help,
|
||||
menu,
|
||||
preferences,
|
||||
subnav,
|
||||
task
|
||||
// window
|
||||
task,
|
||||
window
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ export default {
|
||||
'app-log-path': 'App log path',
|
||||
'download-session-path': 'Download session path',
|
||||
'factory-reset': 'Factory Reset',
|
||||
'factory-reset-confirm': 'Are you sure you want to revert to factory settings?',
|
||||
'lab-warning': '⚠️ Enabling lab features may cause app crashes or data loss, decide for yourself!',
|
||||
'download-protocol': 'Protocol',
|
||||
'support-more-download-protocols': 'Enable more download protocols support',
|
||||
|
||||
@@ -4,6 +4,7 @@ export default {
|
||||
'stopped': 'Stopped',
|
||||
'new-task': 'New Task',
|
||||
'new-bt-task': 'New BT Task',
|
||||
'open-file': 'Open Torrent File...',
|
||||
'uri-task': 'URL',
|
||||
'torrent-task': 'Torrent',
|
||||
'uri-task-tip': 'One task url per line (support magnet)',
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
export default {
|
||||
'engine-version': 'Version du moteur',
|
||||
'about': 'À Propos',
|
||||
'release': 'Release',
|
||||
'support': 'Support'
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
export default {
|
||||
'task-list': 'Liste des tâches',
|
||||
'add-task': 'Ajouter une tâche',
|
||||
'about': 'À Propos de Motrix',
|
||||
'preferences': 'Préférences...',
|
||||
'check-for-updates': 'Vérifier les mises à jour...',
|
||||
'check-for-updates-title': 'Vérifier les mises à jour',
|
||||
'update-available-message': 'Une nouvelle version de Motrix est disponible, mise à jour maintenant?',
|
||||
'update-not-available-message': 'Vous êtes à jour!',
|
||||
'update-downloaded-message': 'Prêt à installer...',
|
||||
'update-error-message': 'Erreur de mise à jour',
|
||||
'engine-damaged-message': 'Le moteur est endommagé, veuillez réinstaller : (',
|
||||
'engine-missing-message': 'Le moteur est manquant, veuillez réinstaller : (',
|
||||
'system-error-title': 'Erreur système',
|
||||
'system-error-message': 'L\'application n\'a pas pu démarrer: {{message}}',
|
||||
'hide': 'Cacher Motrix',
|
||||
'hide-others': 'Cacher les autres',
|
||||
'unhide': 'Tout montrer',
|
||||
'show': 'Montrer Motrix',
|
||||
'quit': 'Quitter Motrix',
|
||||
'under-development-message': 'Désolé, cette fonctionnalité est en cours de développement...',
|
||||
'yes': 'Oui',
|
||||
'no': 'Non',
|
||||
'cancel': 'Annuler',
|
||||
'submit': 'Envoyer',
|
||||
'gt1d': '> 1 jour',
|
||||
'hour': 'h',
|
||||
'minute': 'm',
|
||||
'second': 's'
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export default {
|
||||
'undo': 'Annuler la dernière action',
|
||||
'redo': 'Rétablir la dernière action',
|
||||
'cut': 'Couper',
|
||||
'copy': 'Copier',
|
||||
'paste': 'Coller',
|
||||
'delete': 'Supprimer',
|
||||
'select-all': 'Tout sélectionner'
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export default {
|
||||
'official-website': 'Site web de Motrix ',
|
||||
'manual': 'Manuel',
|
||||
'release-notes': 'Notes de version...',
|
||||
'report-problem': 'Signaler un problème',
|
||||
'toggle-dev-tools': 'Activer les outils pour développeurs'
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import about from './about'
|
||||
import app from './app'
|
||||
import edit from './edit'
|
||||
import help from './help'
|
||||
import menu from './menu'
|
||||
import preferences from './preferences'
|
||||
import subnav from './subnav'
|
||||
import task from './task'
|
||||
import window from './window'
|
||||
|
||||
export default {
|
||||
about,
|
||||
app,
|
||||
edit,
|
||||
help,
|
||||
menu,
|
||||
preferences,
|
||||
subnav,
|
||||
task,
|
||||
window
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export default {
|
||||
'app': 'Motrix',
|
||||
'file': 'Fichier',
|
||||
'task': 'Tâche',
|
||||
'edit': 'Editer',
|
||||
'window': 'Fenêtre',
|
||||
'help': 'Aide'
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
export default {
|
||||
'basic': 'Basique',
|
||||
'advanced': 'Avancé',
|
||||
'lab': 'Labo',
|
||||
'save': 'Sauver et appliquer',
|
||||
'discard': 'Annuler les changement',
|
||||
'startup': 'Démarrage',
|
||||
'auto-resume-all': 'Reprendre les tâches non terminées',
|
||||
'default-dir': 'Répertoire par défaut',
|
||||
'mas-default-dir-tip': 'En raison des restrictions d\'autorisations du bac à sable de l\'App Store, il est recommandé de définir le répertoire de téléchargement par défaut sur le répertoire Téléchargements.',
|
||||
'task-manage': 'Tâches',
|
||||
'max-concurrent-downloads': 'Nombre de tâches active au maximum',
|
||||
'max-connection-per-server': 'Nombre maximum de connexions par serveurs',
|
||||
'new-task-show-downloading': 'Montrer automatiquement les téléchargements après l\'ajout d\'une tâche',
|
||||
'continue': 'Continuer',
|
||||
'task-completed-notify': 'Notifier à la fin d\'un téléchargement',
|
||||
'auto-purge-record': 'Purger l\'historique de téléchargement lorsque vous quittez l\'application',
|
||||
'ui': 'UI',
|
||||
'language': 'Langues',
|
||||
'change-language': 'Changer la langue',
|
||||
'hide-app-menu': 'Cacher le menu de l\'application (Windows & Linux uniquement)',
|
||||
'proxy': 'Proxy',
|
||||
'use-proxy': 'Activer le Proxy',
|
||||
'developer': 'Développeur',
|
||||
'mock-user-agent': 'Mock User-Agent',
|
||||
'app-log-path': 'Chemin des logs',
|
||||
'download-session-path': 'Chemin de la session de téléchargement',
|
||||
'factory-reset': 'Réinitialisation',
|
||||
'factory-reset-confirm': 'Êtes vous sûr de vouloir réinitialiser les paramètres',
|
||||
'lab-warning': '⚠️ Activer les fonctionalités labo peut causer des crash ou la perte de données !',
|
||||
'download-protocol': 'Protocole',
|
||||
'support-more-download-protocols': 'Activer les protocoles de téléchargement suplémentaires',
|
||||
'browser-extensions': 'Extensions',
|
||||
'baidu-exporter': 'BaiduExporter',
|
||||
'browser-extensions-tip': 'Fourni par la communauté, ',
|
||||
'baidu-exporter-help': 'Cliquez ici pour voir l\'utilisation'
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export default {
|
||||
'task-list': 'Tâches',
|
||||
'preferences': 'Préférences'
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
export default {
|
||||
'active': 'Actives',
|
||||
'waiting': 'En attente',
|
||||
'stopped': 'Stopées',
|
||||
'new-task': 'Nouvelle Tâche',
|
||||
'new-bt-task': 'Nouvelle Tâche BT',
|
||||
'open-file': 'Ouvrir un fichier torrent...',
|
||||
'uri-task': 'Lien',
|
||||
'torrent-task': 'Torrent',
|
||||
'uri-task-tip': 'Un lien par ligne (supporte les magnets)',
|
||||
'thunder-link-tip': 'Astuce: Les liens Thunder ne doivent pas être téléchargés après décodage',
|
||||
'task-name': 'Nom de la tâche',
|
||||
'task-out': 'Renommer',
|
||||
'task-out-tip': 'Optionel, supporte une seule tâche',
|
||||
'task-split': 'Découpages',
|
||||
'task-dir': 'Répertoire',
|
||||
'pause-task': 'Mettre en Pause',
|
||||
'task-ua': 'UA',
|
||||
'task-user-agent': 'User-Agent',
|
||||
'task-referer': 'Référent',
|
||||
'task-cookie': 'Cookie',
|
||||
'navigate-to-downloading': 'Aller au Téléchargement',
|
||||
'show-advanced-options': 'Options Avancées',
|
||||
'copyright-warning': 'Avertissement Copyright',
|
||||
'copyright-warning-message': 'Le fichier que vous voulez télécharger peut être une vidéo ou de l\'audio soumie aux copyright, verifiez que vous possédez bien sa license.',
|
||||
'copyright-yes': 'Oui, je l\'ai',
|
||||
'copyright-no': 'Non',
|
||||
'copyright-error-message': 'Ajout de la tâche annulé, pas de copyright',
|
||||
'pause-task-success': 'Mise en pause de "{{taskName}}" avec succés',
|
||||
'pause-task-fail': 'Mise en pause de "{{taskName}}" échouée',
|
||||
'resume-task': 'Reprendre',
|
||||
'resume-task-success': 'Reprise de "{{taskName}}" avec succés',
|
||||
'resume-task-fail': 'Reprise de "{{taskName}}" échouée',
|
||||
'delete-task': 'Supprimer',
|
||||
'delete-selected-tasks': 'Supprimer la séléction',
|
||||
'delete-task-confirm': 'Étes vous sûr de vouloir supprimer "{{taskName}}" ?',
|
||||
'delete-task-label': 'Supprimer avec les fichiers',
|
||||
'delete-task-success': 'Suppression de "{{taskName}}" avec succés',
|
||||
'delete-task-fail': 'Suppression de "{{taskName}}" échouée',
|
||||
'remove-task-file-fail': 'Impossible de supprimer la tâche, s\'il vous plait supprimez la manuellement',
|
||||
'remove-task-config-file-fail': 'Impossible de supprimer le fichier de configuration de la tâche, s\'il vous plait supprimez le manuellement',
|
||||
'move-task-up': 'Déplacer vers le haut',
|
||||
'move-task-down': 'Déplacer vers le bas',
|
||||
'pause-all-task': 'Tout mettre en pause',
|
||||
'pause-all-task-success': 'Mise en pause réussie',
|
||||
'pause-all-task-fail': 'Mise en pause échouée',
|
||||
'resume-all-task': 'Tout reprendre',
|
||||
'resume-all-task-success': 'Reprise réussie',
|
||||
'resume-all-task-fail': 'Reprise échouée',
|
||||
'clear-recent-tasks': 'Effacer les tâches récentes',
|
||||
'purge-record': 'Purger les tâches récentes',
|
||||
'purge-record-success': 'Purge des tâches récentes réussie',
|
||||
'purge-record-fail': 'Purge des tâches récentes échouée',
|
||||
'refresh-list': 'Rafraichir la liste des tâches',
|
||||
'no-task': 'Aucun téléchargement en cours',
|
||||
'copy-link': 'Copier le lien',
|
||||
'copy-link-success': 'Lien copié',
|
||||
'remove-record': 'Effacer l\'enregistrement des tâches',
|
||||
'remove-record-confirm': 'Étes vous sûr de vouloir effacer "{{taskName}}" ?',
|
||||
'remove-record-label': 'Supprimer avec les fichiers',
|
||||
'remove-record-success': '"{{taskName}}" éffacée',
|
||||
'remove-record-fail': '"{{taskName}}" n\'a pas été éffacée',
|
||||
'show-in-folder': 'Montrer la tâche dans le dossier',
|
||||
'file-not-exist': 'Le fichier n\'existe pas ou a été supprimé',
|
||||
'file-path-error': 'Erreur de lien sur le fichier',
|
||||
'opening-task-message': 'Ouverture de "{{taskName}}" ...',
|
||||
'get-task-name': 'Récupération du nom de la tâche...',
|
||||
'remaining-prefix': 'Restant',
|
||||
'select-torrent': 'Glissez-déposez un torrent ici, ou cliquez pour en choisir un',
|
||||
'task-info-dialog-title': '{{title}} Details',
|
||||
'download-start-message': 'Téléchargment de {{taskName}}',
|
||||
'download-pause-message': 'Mise en pause de {{taskName}}',
|
||||
'download-stop-message': '{{taskName}} téléchargment arrété',
|
||||
'download-error-message': '{{taskName}} une erreur c\'est produite',
|
||||
'download-complete-message': '{{taskName}} téléchargement terminé',
|
||||
'download-complete-notify': 'Téléchargement Terminé',
|
||||
'download-fail-message': '{{taskName}} téléchargement échoué',
|
||||
'download-fail-notify': 'Téléchargement Échoué'
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export default {
|
||||
'reload': 'Recharger',
|
||||
'close': 'Fermer',
|
||||
'minimize': 'Réduire',
|
||||
'zoom': 'Zoom',
|
||||
'toggle-fullscreen': 'Passer en mode Plein écran',
|
||||
'front': 'Tout mettre au premier plan'
|
||||
}
|
||||
@@ -1,28 +1,74 @@
|
||||
/**
|
||||
* If you want to contribute translation, please add a 'locale' here.
|
||||
* For the value of locale, please refer to the link below.
|
||||
* https://electronjs.org/docs/api/locales
|
||||
* Welcome to translate to more versions in other languages.
|
||||
* Please read the translation guide before starting work.
|
||||
* https://github.com/agalwood/Motrix/blob/master/CONTRIBUTING.md#-translation-guide
|
||||
*
|
||||
* Please keep the locale key in alphabetical order.
|
||||
*/
|
||||
export const supportLanguages = [
|
||||
'en-US',
|
||||
'zh-CN'
|
||||
export const availableLanguages = [
|
||||
{
|
||||
value: 'de',
|
||||
label: 'Deutsch'
|
||||
},
|
||||
{
|
||||
value: 'en-US',
|
||||
label: 'English'
|
||||
},
|
||||
{
|
||||
value: 'fr',
|
||||
label: 'Français'
|
||||
},
|
||||
{
|
||||
value: 'pt-BR',
|
||||
label: 'Português (Brasil)'
|
||||
},
|
||||
{
|
||||
value: 'tr',
|
||||
label: 'Türkçe'
|
||||
},
|
||||
{
|
||||
value: 'zh-CN',
|
||||
label: '简体中文'
|
||||
},
|
||||
{
|
||||
value: 'zh-TW',
|
||||
label: '繁體中文'
|
||||
}
|
||||
]
|
||||
|
||||
function checkLngIsAvailable (locale) {
|
||||
return availableLanguages.some((lng) => lng.value === locale)
|
||||
}
|
||||
|
||||
/**
|
||||
* getLanguage
|
||||
* @param { String } locale
|
||||
* https://electronjs.org/docs/api/locales
|
||||
*/
|
||||
export function getLanguage (locale = 'en-US') {
|
||||
if (supportLanguages.includes(locale)) {
|
||||
if (checkLngIsAvailable(locale)) {
|
||||
return locale
|
||||
}
|
||||
|
||||
if (locale.startsWith('de')) {
|
||||
return 'de'
|
||||
}
|
||||
|
||||
if (locale.startsWith('en')) {
|
||||
return 'en-US'
|
||||
}
|
||||
|
||||
// If there is a pt-PT translation in the future,
|
||||
// here will fallback to pt-PT.
|
||||
if (locale.startsWith('pt')) {
|
||||
return 'pt-BR'
|
||||
}
|
||||
|
||||
if (locale.startsWith('zh')) {
|
||||
return 'zh-CN'
|
||||
}
|
||||
|
||||
if (locale.startsWith('fr')) {
|
||||
return 'fr'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
export default {
|
||||
'engine-version': 'Versão da Engine',
|
||||
'about': 'Sobre',
|
||||
'release': 'Release',
|
||||
'support': 'Suporte'
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
export default {
|
||||
'task-list': 'Lista de Tarefas',
|
||||
'add-task': 'Adicionar Tarefa',
|
||||
'about': 'Sobre o Motrix',
|
||||
'preferences': 'Preferências...',
|
||||
'check-for-updates': 'Verificar por Atualizações...',
|
||||
'check-for-updates-title': 'Verificar por Atualizações',
|
||||
'update-available-message': 'Uma nova versão do Motrix está disponível, atualize agora?',
|
||||
'update-not-available-message': 'Você esta atualizado!',
|
||||
'update-downloaded-message': 'Pronto para instalar...',
|
||||
'update-error-message': 'Atualizar erro',
|
||||
'engine-damaged-message': 'O motor está danificado, por favor, reinstale : (',
|
||||
'engine-missing-message': 'O motor está faltando, por favor, reinstale : (',
|
||||
'system-error-title': 'Erro do sistema',
|
||||
'system-error-message': 'O aplicativo falhou ao iniciar: {{message}}',
|
||||
'hide': 'Ocultar Motrix',
|
||||
'hide-others': 'Ocultar Outros',
|
||||
'unhide': 'Exibir Todos',
|
||||
'show': 'Exibir Motrix',
|
||||
'quit': 'Sair do Motrix',
|
||||
'under-development-message': 'Desculpe, essa funcionalidade está em desenvolvimento...',
|
||||
'yes': 'Sim',
|
||||
'no': 'Não',
|
||||
'cancel': 'Cancelar',
|
||||
'submit': 'Enviar',
|
||||
'gt1d': '> 1 dia',
|
||||
'hour': 'h',
|
||||
'minute': 'm',
|
||||
'second': 's'
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export default {
|
||||
'undo': 'Desfazer',
|
||||
'redo': 'Refazer',
|
||||
'cut': 'Recortar',
|
||||
'copy': 'Copiar',
|
||||
'paste': 'Copiar',
|
||||
'delete': 'Apagar',
|
||||
'select-all': 'Selecionar Tudo'
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export default {
|
||||
'official-website': 'Motrix Website',
|
||||
'manual': 'Manual',
|
||||
'release-notes': 'Notas de Lançamento...',
|
||||
'report-problem': 'Reportar um Problema',
|
||||
'toggle-dev-tools': 'Alternar Developer Tools'
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import about from './about'
|
||||
import app from './app'
|
||||
import edit from './edit'
|
||||
import help from './help'
|
||||
import menu from './menu'
|
||||
import preferences from './preferences'
|
||||
import subnav from './subnav'
|
||||
import task from './task'
|
||||
import window from './window'
|
||||
|
||||
export default {
|
||||
about,
|
||||
app,
|
||||
edit,
|
||||
help,
|
||||
menu,
|
||||
preferences,
|
||||
subnav,
|
||||
task,
|
||||
window
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user