Compare commits

..

83 Commits

Author SHA1 Message Date
Dr_rOot 10a8f0bd16 fix: remove pacman && update version to 1.1.3 2019-02-10 23:14:47 +08:00
Dr_rOot d3c40a8fc3 fix: remove rpm && update version to 1.1.2 2019-02-10 23:04:30 +08:00
Dr_rOot 34a9247270 fix: update version to 1.1.1 2019-02-10 22:52:48 +08:00
Dr_rOot 0b0f9b41e9 feat: add more linux targets 2019-02-10 22:51:47 +08:00
Dr_rOot 827eb7c32e feat: update version to 1.1.0 2019-02-10 22:23:32 +08:00
Dr_rOot 0b598f6c17 feat: add zip to win target 2019-02-09 20:54:54 +08:00
Dr_rOot 19e7394266 Merge branch 'master' of github.com:agalwood/Motrix 2019-02-09 18:18:44 +08:00
Dr_rOot f6b345ec55 fix: i18n update 2019-02-09 18:16:27 +08:00
Dr_rOot 091201d7ff fix: remove resume and pause message notify 2019-02-09 18:12:49 +08:00
Dr_rOot b109764b8e Update issue templates 2019-02-07 22:34:18 +08:00
Dr_rOot 79a488b863 doc: update readme 2019-02-06 17:17:26 +08:00
Dr_rOot 962c8a6516 fix: temp hide task item action 'more' 2019-02-06 17:17:13 +08:00
Dr_rOot f94cd01a3a Merge branch 'feature/i18next_201901042000'
# Conflicts:
#	README.md
#	src/main/menus/en-US/linux.json
#	src/main/menus/en-US/win32.json
#	src/main/menus/zh-CN/linux.json
#	src/main/menus/zh-CN/win32.json
#	src/renderer/pages/index/App.vue
2019-02-01 21:22:41 +08:00
Dr_rOot 31081bbbb2 fix: add under development message 2019-01-31 23:08:42 +08:00
Dr_rOot 0d1ba16525 refactor: remove console 2019-01-31 23:08:11 +08:00
Dr_rOot 5b4b00ae41 refactor: locale manager 2019-01-31 23:07:08 +08:00
Dr_rOot e0ca5d8724 doc: add touch bar 2019-01-27 21:54:03 +08:00
Dr_rOot fd5b21c271 fix: addTask with multi uris fail #33 2019-01-25 22:19:33 +08:00
Dr_rOot ac5e2f755c doc: add platform badge 2019-01-23 22:00:40 +08:00
Dr_rOot a4415f0688 doc: add app ui screenshot 2019-01-23 21:57:41 +08:00
Dr_rOot 8a2bb03b62 doc: delete related files when removing tasks 2019-01-22 23:56:10 +08:00
Dr_rOot 7011160587 feat: autofill resource uri when open add task 2019-01-22 22:41:11 +08:00
Dr_rOot 31fdff3d3b doc: add total download badge 2019-01-22 20:54:19 +08:00
Dr_rOot 580bb5d622 doc: fix license 2019-01-21 18:04:43 +08:00
Dr_rOot d5a51a8422 doc: readme i18n 2019-01-21 18:02:41 +08:00
Dr_rOot 5f5b22d8d3 doc: update readme 2019-01-20 22:47:00 +08:00
Dr_rOot 397f689be7 fix: i18n error 2019-01-20 22:38:38 +08:00
Dr_rOot 3ddffe6daf refactor: code clean 2019-01-20 22:35:39 +08:00
Dr_rOot ab1861b068 feat: i18n change locale 2019-01-20 22:34:28 +08:00
Dr_rOot 5bf870acdc feat: i18n refactor 2019-01-20 21:52:43 +08:00
Dr_rOot d85f4ea8d4 fix: ConfigManager add getLocale util 2019-01-20 21:47:04 +08:00
Dr_rOot 0a93c1954d fix: menu text 2019-01-20 21:44:42 +08:00
Dr_rOot c4df9ff34e feat: i18n add task 2019-01-19 23:03:00 +08:00
Dr_rOot 648587f52c feat: open task when double click completed task
#23
2019-01-19 21:53:47 +08:00
Dr_rOot bc17c2d685 fix: task i18n params error 2019-01-19 21:51:11 +08:00
Dr_rOot 6e7327a3fe feat: add support for hide app menu on linux 2019-01-17 11:08:53 +08:00
Dr_rOot db15cd959b fix: i18n key error 2019-01-16 23:46:13 +08:00
Dr_rOot ff43994902 feat: hide app menu 2019-01-16 23:44:59 +08:00
Dr_rOot 8226e14e0a fix: titlebar style background 2019-01-16 12:53:32 +08:00
Dr_rOot f5b30efc7d refactor: new title-bar component 2019-01-15 23:48:50 +08:00
Dr_rOot 4c27c36e90 fix: windows manager getWindows() forEach error 2019-01-11 17:51:53 +08:00
Dr_rOot 9dd950e510 fix: windows manager getWindows() forEach error 2019-01-11 17:49:06 +08:00
Dr_rOot fffa7b9839 feat: app about add release link 2019-01-09 23:34:20 +08:00
Dr_rOot 2d3ca45c87 fix: preferences label 2019-01-08 23:14:09 +08:00
Dr_rOot c0f032a6c6 fix: add package 2019-01-07 21:50:19 +08:00
Dr_rOot f8848ba0e5 feat: i18n main logic 2019-01-07 21:49:14 +08:00
Dr_rOot 33a3229c22 feat: engine client i18n 2019-01-07 21:27:21 +08:00
Dr_rOot 5a626cece9 feat: task i18n 2019-01-07 20:17:22 +08:00
Dr_rOot 16c80e75b5 feat: preferences i18n 2019-01-06 23:14:13 +08:00
Dr_rOot 4c604304d8 feat: add determineLocale util 2019-01-06 21:39:54 +08:00
Dr_rOot a921695efc feat: tasks i18n 2019-01-06 21:33:45 +08:00
Dr_rOot 09dfe1c8ea feat: select torrent i18n 2019-01-06 21:32:41 +08:00
Dr_rOot 1fbaeefca5 feat: app subnav i18n 2019-01-06 21:25:02 +08:00
Dr_rOot 9a969040ef feat: task list i18n 2019-01-06 21:19:07 +08:00
Dr_rOot b7615a178b feat: task item actions i18n 2019-01-06 21:18:27 +08:00
Dr_rOot 894b9c9a54 feat: task actions i18n 2019-01-06 21:14:20 +08:00
Dr_rOot 6dc4b9718e feat: app about i18n 2019-01-06 21:03:35 +08:00
Dr_rOot 6435ad6594 refactor: remove code 2019-01-06 18:31:34 +08:00
Dr_rOot 173e071a86 fix: linux application menu command chain 2019-01-06 18:31:34 +08:00
Dr_rOot 8812b6409e fix: win32 & linux first menu label text to File 2019-01-06 18:31:34 +08:00
Dr_rOot 56bd63a418 refactor: remove code 2019-01-06 18:31:34 +08:00
Dr_rOot 915b2fcaa6 fix: bt enable dht 2019-01-06 18:31:34 +08:00
Dr_rOot 7eb63f105a fix: only show title bar when is renderer 2019-01-06 18:31:34 +08:00
Dr_rOot d6bc8a0436 refactor: remove unuse style code 2019-01-06 18:31:34 +08:00
Dr_rOot 6ea8603074 fix: disable text selection within a draggable 2019-01-06 18:31:34 +08:00
Dr_rOot a652e7b893 refactor: remove code 2019-01-06 18:25:41 +08:00
Dr_rOot 0e4b7dbc43 fix: linux application menu command chain 2019-01-06 18:25:01 +08:00
Dr_rOot e73e9c5b27 fix: win32 & linux first menu label text to File 2019-01-06 18:22:21 +08:00
Dr_rOot 078ddab4ad refactor: remove code 2019-01-06 18:16:07 +08:00
Dr_rOot 749c77ab3e refactor: store app module 2019-01-06 18:10:21 +08:00
Dr_rOot 7c2eb7997a feat: add en locales 2019-01-06 18:08:22 +08:00
Dr_rOot 6beb1ca5a4 feat: add zh locales 2019-01-06 18:08:15 +08:00
Dr_rOot b9bd866d4b fix: bt enable dht 2019-01-06 17:53:08 +08:00
Dr_rOot 08c96b5728 fix: only show title bar when is renderer 2019-01-05 19:38:36 +08:00
Dr_rOot 4f77a8ebdc refactor: remove unuse style code 2019-01-04 20:18:20 +08:00
Dr_rOot 75d7fad29f fix: disable text selection within a draggable 2019-01-04 20:05:53 +08:00
Dr_rOot 0adc62f04c refactor: change will deprecated api 2019-01-04 16:31:18 +08:00
Dr_rOot dadc0801c2 fix: update readme 2019-01-04 13:04:55 +08:00
Dr_rOot 334d4e6386 feat: support thunder links 2019-01-04 13:03:40 +08:00
Dr_rOot 47b8ad6e56 fix: change default seed-ratio 2019-01-03 22:08:15 +08:00
Dr_rOot c621fc457d fix: remove unuse preference basic form keys 2019-01-03 22:07:16 +08:00
Dr_rOot 6ea3112691 fix: update version to 1.0.10 2019-01-03 10:19:13 +08:00
Dr_rOot 8c63f97d8e fix: change win32 aria2c to 32bit 2019-01-03 10:12:21 +08:00
85 changed files with 4737 additions and 1014 deletions
+34
View File
@@ -0,0 +1,34 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: "bug \U0001F41E"
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
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]
**Additional context**
Add any other context about the problem here.
+20
View File
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement ✨
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+82
View File
@@ -0,0 +1,82 @@
# Motrix
<a href="https://motrix.app">
<img src="https://cdn.nlark.com/yuque/0/2018/png/129147/1543735425232-a5d2c99f-d788-43e4-9781-558ff6d21027.png" width="256" alt="App Icon" />
</a>
[English](./README.md) | 简体中文
## 一款全能的下载工具
[![Build Status](https://travis-ci.org/agalwood/Motrix.svg?branch=master)](https://travis-ci.org/agalwood/Motrix) [![Build status](https://ci.appveyor.com/api/projects/status/l11d5h05xwwcvoux/branch/master?svg=true)](https://ci.appveyor.com/project/agalwood/motrix/branch/master) ![Total Downloads](https://img.shields.io/github/downloads/agalwood/Motrix/total.svg) ![Support Platforms](https://camo.githubusercontent.com/a50c47295f350646d08f2e1ccd797ceca3840e52/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f706c6174666f726d2d6d61634f5325323025374325323057696e646f77732532302537432532304c696e75782d6c69676874677265792e737667)
我是个兴趣使然的桌面应用开发者🤓,利用搬砖之余开发了 Motrix。
Motirx 是一款全能的下载工具,支持下载 HTTP、FTP、BT、磁力链、百度网盘等资源。它的界面简洁易用,希望大家喜欢 👻。
✈️ 去 [官网](https://motrix.app) 逛逛
## 💽 安装稳定版
[GitHub](https://github.com/agalwood/Motrix/releases) 和 [官网](https://motrix.app) 提供了已经编译好的稳定版安装包,当然你也可以自己克隆代码编译打包。
> 七牛CDN流量🔥烧不起,高峰时一天烧了110G的流量💸💸💸
## ✨ 特性
- 🕹 简洁明了的图形操作界面
- 🧲 支持BT和磁力链任务
- 🤫 支持下载百度云盘资源
- 🎛 最高支持 10 个任务同时下载
- 🚀 单任务最高支持 64 线程下载
- 🕶 模拟用户代理UA
- 🔔 下载完成后通知
- 💻 支持触控栏快捷健 (Mac 专享)
- 🗑 移除任务时可同时删除相关文件
- 🌍 国际化(可选择简体中文或英文界面)
- 🎏 ...
## 🖥 应用界面
![motrix-screenshot-task-cn.png](https://cdn.nlark.com/yuque/0/2019/png/129147/1548251088177-21762a41-3975-4417-bf54-6f64aeb0f20d.png)
## ⌨️ 本地开发
### 克隆代码
```bash
git clone git@github.com:agalwood/Motrix.git
```
### 安装依赖
```bash
cd Motrix
npm install
```
天朝大陆用户建议使用淘宝的npm源
```bash
npm config set registry 'https://registry.npm.taobao.org'
export ELECTRON_MIRROR='https://npm.taobao.org/mirrors/electron/'
export SASS_BINARY_SITE='https://npm.taobao.org/mirrors/node-sass'
```
如果喜欢 [Yarn](https://yarnpkg.com/),也可以使用 `yarn` 安装依赖
### 开发模式
```bash
npm run dev
```
### 编译打包
```bash
npm run build
```
完成之后可以在项目的 `release` 目录看到编译打包好的应用文件
## 🛠 技术栈
- [Electron](https://electronjs.org/)
- [Vue](https://vuejs.org/) + [VueX](https://vuex.vuejs.org/) + [Element](https://element.eleme.io)
- [Aria2](https://aria2.github.io/) (注:macOS 和 Linux 版本使用的是 64 位的 aria2cWindows 版使用的 32 位的)
## ☑️ TODO
开发计划请移步 [Trello](https://trello.com/b/qNUzA0bv/motrix) 查看
## 🤝 参与共建 [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
如果你有兴趣参与共同开发,欢迎 FORK 和 PR。
## 📜 开源许可
基于 [MIT license](https://opensource.org/licenses/MIT) 许可进行开源。
+41 -32
View File
@@ -1,65 +1,74 @@
# Motrix
<a href="https://motrix.app">
<img src="https://motrix.app/images/app-icon@2x.png" width="256" alt="App Icon" />
<img src="https://cdn.nlark.com/yuque/0/2018/png/129147/1543735425232-a5d2c99f-d788-43e4-9781-558ff6d21027.png" width="256" alt="App Icon" />
</a>
## 一款全能的下载工具
[![Build Status](https://travis-ci.org/agalwood/Motrix.svg?branch=master)](https://travis-ci.org/agalwood/Motrix)[![Build status](https://ci.appveyor.com/api/projects/status/l11d5h05xwwcvoux/branch/master?svg=true)](https://ci.appveyor.com/project/agalwood/motrix/branch/master)
## A full-featured download manager.
[![Build Status](https://travis-ci.org/agalwood/Motrix.svg?branch=master)](https://travis-ci.org/agalwood/Motrix) [![Build status](https://ci.appveyor.com/api/projects/status/l11d5h05xwwcvoux/branch/master?svg=true)](https://ci.appveyor.com/project/agalwood/motrix/branch/master) ![Total Downloads](https://img.shields.io/github/downloads/agalwood/Motrix/total.svg) ![Support Platforms](https://camo.githubusercontent.com/a50c47295f350646d08f2e1ccd797ceca3840e52/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f706c6174666f726d2d6d61634f5325323025374325323057696e646f77732532302537432532304c696e75782d6c69676874677265792e737667)
English | [简体中文](./README-CN.md)
支持下载 HTTPFTP、BT、磁力链、百度网盘等资源
Motrix is a full-featured download manager that support downloading HTTP, FTP, BitTorrent, Magnet, Baidu Net Disk etc.
<span style="font-size: 30px">我</span>是个兴趣使然的桌面应用开发者🤓,出于兴趣爱好,利用搬砖之余开发了 [MO 1.0](https://moapp.me) 版本,做出来有大半年了,没做过什么推广,所以大家可能都没怎么听过这个应用吧~👻~
It has a clean and simple interface and is easy to use. I hope you will like it 👻.
本着自己用得舒(折)服(腾)😌的想法,🤠撸出了个全新的版本,并更名为 Motrix。新版本不仅优化了性能,还重新设计了图形操作界面,操作更简便!
✈️ [Official Website](https://motrix.app)
官网提供了已经编译好的应用安装包([去官网下载](https://motrix.app)),当然你也可以自己克隆代码进行编译打包。
## 💽 Installation
Download from [GitHub Releases](https://github.com/agalwood/Motrix/releases) and install it.
## 🛠 技术栈
- [Electron](https://electronjs.org/)
- [Vue](https://vuejs.org/) + [VueX](https://vuex.vuejs.org/) + [Element](https://element.eleme.io)
- [Aria2](https://aria2.github.io/)
## ✨ 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
- 🕶 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.
- 🎏 ...
## 📦 自行编译
## 🖥 User Interface
![motrix-screenshot-task-en.png](https://cdn.nlark.com/yuque/0/2019/png/129147/1548251350313-73aa0d60-ee31-4405-bdb9-1793e3fd46ef.png)
### 克隆代码
## ⌨️ Development
### Clone Code
```bash
git clone git@github.com:agalwood/Motrix.git
```
### 安装依赖
### Install Dependencies
```bash
cd Motrix
npm install
```
天朝大陆用户建议使用淘宝的npm源
```bash
npm config set registry 'https://registry.npm.taobao.org'
export ELECTRON_MIRROR='https://npm.taobao.org/mirrors/electron/'
export SASS_BINARY_SITE='https://npm.taobao.org/mirrors/node-sass'
```
如果喜欢 [Yarn](https://yarnpkg.com/),也可以使用 `yarn` 安装依赖
If you like [Yarn](https://yarnpkg.com/), you can also use `yarn` to install dependencies.
### 开发模式
### Dev Mode
```bash
npm run dev
```
### 编译打包
### Build Release
```bash
npm run build
```
完成之后可以在项目的 release 目录看到编译打包好的应用文件
After build finish, you can see the compiled packaged application file in the `release` directory of the project.
## 🛠 Technology Stack
- [Electron](https://electronjs.org/)
- [Vue](https://vuejs.org/) + [VueX](https://vuex.vuejs.org/) + [Element](https://element.eleme.io)
- [Aria2](https://aria2.github.io/) (Note: macOS and Linux versions use 64-bit aria2c, Windows version uses 32-bit)
## ☑️ TODO
- [ ] 国际化支持
- [ ] macOS Mojave 深色模式
- [ ] Windows 和 Linux 版本理论上会有,还未调试
- [ ] 测试用例
Development Roadmap see: [Trello](https://trello.com/b/qNUzA0bv/motrix)
## 🤝 参与共建 [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
如果你有兴趣参与共同开发,欢迎 FORK 和 PR。
## 🤝 Contribute [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
If you are interested in participating in joint development, Fork and PR are welcome.
## 📜 开源许可
基于 [MIT license](https://opensource.org/licenses/MIT) 许可进行开源。
## 📜 License
[MIT](https://opensource.org/licenses/MIT) Copyright (c) 2018-present Dr_rOot
+4 -4
View File
@@ -77,22 +77,22 @@ listen-port=51413
# 单个种子最大连接数, 默认:55
#bt-max-peers=55
# 打开DHT功能, PT需要禁用, 默认:true
enable-dht=false
# enable-dht=false
# 打开IPv6 DHT功能, PT需要禁用
#enable-dht6=false
# DHT网络监听端口, 默认:6881-6999
#dht-listen-port=6881-6999
# 本地节点查找, PT需要禁用, 默认:false
#bt-enable-lpd=false
bt-enable-lpd=true
# 种子交换, PT需要禁用, 默认:true
#enable-peer-exchange=false
enable-peer-exchange=true
# 每个种子限速, 对少种的PT很有用, 默认:50K
#bt-request-peer-speed-limit=50K
# 客户端伪装, PT需要
peer-id-prefix=-TR2770-
user-agent=Transmission/2.94
# 当种子的分享率达到这个数时, 自动停止做种, 0为一直做种, 默认:1.0
seed-ratio=0
seed-ratio=1.0
# 强制保存会话, 即使任务已经完成, 默认:false
# 较新的版本开启后会在任务完成后依然保留.aria2文件
#force-save=false
+4 -4
View File
@@ -77,22 +77,22 @@ listen-port=51413
# 单个种子最大连接数, 默认:55
#bt-max-peers=55
# 打开DHT功能, PT需要禁用, 默认:true
enable-dht=false
# enable-dht=false
# 打开IPv6 DHT功能, PT需要禁用
#enable-dht6=false
# DHT网络监听端口, 默认:6881-6999
#dht-listen-port=6881-6999
# 本地节点查找, PT需要禁用, 默认:false
#bt-enable-lpd=false
bt-enable-lpd=true
# 种子交换, PT需要禁用, 默认:true
#enable-peer-exchange=false
enable-peer-exchange=true
# 每个种子限速, 对少种的PT很有用, 默认:50K
#bt-request-peer-speed-limit=50K
# 客户端伪装, PT需要
peer-id-prefix=-TR2770-
user-agent=Transmission/2.94
# 当种子的分享率达到这个数时, 自动停止做种, 0为一直做种, 默认:1.0
seed-ratio=0
seed-ratio=1.0
# 强制保存会话, 即使任务已经完成, 默认:false
# 较新的版本开启后会在任务完成后依然保留.aria2文件
#force-save=false
+4 -4
View File
@@ -77,22 +77,22 @@ listen-port=51413
# 单个种子最大连接数, 默认:55
#bt-max-peers=55
# 打开DHT功能, PT需要禁用, 默认:true
enable-dht=false
# enable-dht=false
# 打开IPv6 DHT功能, PT需要禁用
#enable-dht6=false
# DHT网络监听端口, 默认:6881-6999
#dht-listen-port=6881-6999
# 本地节点查找, PT需要禁用, 默认:false
#bt-enable-lpd=false
bt-enable-lpd=true
# 种子交换, PT需要禁用, 默认:true
#enable-peer-exchange=false
enable-peer-exchange=true
# 每个种子限速, 对少种的PT很有用, 默认:50K
#bt-request-peer-speed-limit=50K
# 客户端伪装, PT需要
peer-id-prefix=-TR2770-
user-agent=Transmission/2.94
# 当种子的分享率达到这个数时, 自动停止做种, 0为一直做种, 默认:1.0
seed-ratio=0
seed-ratio=1.0
# 强制保存会话, 即使任务已经完成, 默认:false
# 较新的版本开启后会在任务完成后依然保留.aria2文件
#force-save=false
Binary file not shown.
+3305 -491
View File
File diff suppressed because it is too large Load Diff
+25 -20
View File
@@ -1,6 +1,6 @@
{
"name": "Motrix",
"version": "1.0.9",
"version": "1.1.3",
"description": "A full-featured download manager",
"homepage": "https://motrix.app",
"author": {
@@ -89,6 +89,7 @@
"win": {
"target": [
"nsis",
"zip",
"portable"
],
"extraResources": {
@@ -106,6 +107,7 @@
"linux": {
"target": [
"deb",
"snap",
"AppImage"
],
"extraResources": {
@@ -127,31 +129,33 @@
]
},
"dependencies": {
"@panter/vue-i18next": "^0.15.0",
"aria2": "^4.0.3",
"axios": "^0.18.0",
"clipboard-polyfill": "^2.7.0",
"electron-debug": "^2.0.0",
"electron-debug": "^2.1.0",
"electron-is": "^3.0.0",
"electron-log": "^2.2.17",
"electron-updater": "^4.0.7",
"element-ui": "^2.4.11",
"element-ui": "^2.5.4",
"forever-monitor": "^1.7.1",
"i18next": "^15.0.0",
"lodash": "^4.17.11",
"normalize.css": "^8.0.1",
"parse-torrent": "^6.1.2",
"svg-innerhtml": "^1.1.0",
"vue": "^2.5.17",
"vue": "^2.6.4",
"vue-electron": "^1.0.6",
"vue-router": "^3.0.2",
"vuex": "^3.0.1",
"vuex": "^3.1.0",
"vuex-router-sync": "^5.0.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.2.2",
"@vue/cli-plugin-eslint": "^3.2.2",
"@vue/cli-service": "^3.2.2",
"@vue/cli-plugin-babel": "^3.4.0",
"@vue/cli-plugin-eslint": "^3.4.0",
"@vue/cli-service": "^3.4.0",
"@vue/eslint-config-standard": "^4.0.0",
"ajv": "^6.6.2",
"ajv": "^6.9.1",
"babel-core": "^6.26.3",
"babel-eslint": "^10.0.1",
"babel-loader": "^7.1.4",
@@ -161,28 +165,28 @@
"babel-preset-stage-0": "^6.24.1",
"babel-register": "^6.26.0",
"babili-webpack-plugin": "^0.1.2",
"cfonts": "^2.2.3",
"cfonts": "^2.4.2",
"chalk": "^2.4.1",
"copy-webpack-plugin": "^4.6.0",
"cross-env": "^5.1.6",
"css-loader": "^1.0.1",
"del": "^3.0.0",
"devtron": "^1.4.0",
"electron": "^4.0.0",
"electron-builder": "^20.38.4",
"electron": "^4.0.4",
"electron-builder": "^20.38.5",
"electron-devtools-installer": "^2.2.4",
"electron-notarize": "^0.0.5",
"electron-osx-sign": "^0.4.11",
"electron-store": "^2.0.0",
"eslint": "^5.11.1",
"eslint": "^5.13.0",
"eslint-config-standard": "^12.0.0",
"eslint-friendly-formatter": "^4.0.1",
"eslint-loader": "^2.1.1",
"eslint-plugin-html": "^4.0.6",
"eslint-plugin-import": "^2.12.0",
"eslint-loader": "^2.1.2",
"eslint-plugin-import": "^2.16.0",
"eslint-plugin-node": "^7.0.1",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^5.1.0",
"file-loader": "^2.0.0",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "0.5.0",
@@ -193,12 +197,13 @@
"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.4.2",
"vue-loader": "^15.6.2",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.5.17",
"webpack": "^4.28.3",
"webpack-cli": "^3.1.2",
"vue-template-compiler": "^2.6.4",
"webpack": "^4.29.3",
"webpack-cli": "^3.2.3",
"webpack-dev-server": "^3.1.14",
"webpack-hot-middleware": "^2.24.3",
"webpack-merge": "^4.1.4"
+12 -8
View File
@@ -18,12 +18,16 @@ export default class Application extends EventEmitter {
this.exceptionHandler = new ExceptionHandler()
this.locale = app.getLocale()
logger.log('[Motrix] Locale: ', this.locale)
this.init()
}
init () {
this.configManager = new ConfigManager()
this.locale = this.configManager.getLocale()
this.windowManager = new WindowManager()
this.windowManager = new WindowManager({
userConfig: this.configManager.getUserConfig()
})
this.engine = new Engine({
systemConfig: this.configManager.getSystemConfig(),
@@ -93,27 +97,27 @@ export default class Application extends EventEmitter {
sendCommandToAll (command, ...args) {
if (!this.emit(command, ...args)) {
this.windowManager.getWindows().forEach(window => {
this.windowManager.getWindowList().forEach(window => {
this.windowManager.sendCommandTo(window, command, ...args)
})
}
}
sendMessageToAll (channel, ...args) {
this.windowManager.getWindows().forEach(window => {
this.windowManager.getWindowList().forEach(window => {
this.windowManager.sendMessageTo(window, channel, ...args)
})
}
initProtocolManager () {
if (is.mas()) {
if (is.dev() || is.mas()) {
return
}
this.protocolManager = new ProtocolManager()
}
handleProtocol (url) {
if (is.mas()) {
if (is.dev() || is.mas()) {
return
}
this.protocolManager.handle(url)
@@ -193,7 +197,7 @@ export default class Application extends EventEmitter {
this.updateManager.check()
})
this.on('application:set-locale', (locale) => {
this.on('application:change-locale', (locale) => {
this.menuManager.setup(locale)
})
+5
View File
@@ -52,6 +52,7 @@ export default class ConfigManager {
defaults: {
'resume-all-when-app-launched': false,
'task-notification': true,
'hide-app-menu': false,
'new-task-show-downloading': true,
'auto-check-for-updates': false,
'update-channel': 'latest',
@@ -82,6 +83,10 @@ export default class ConfigManager {
return this.userConfig.get(key, defaultValue)
}
getLocale () {
return this.getUserConfig('locale') || app.getLocale()
}
setSystemConfig (...args) {
this.systemConfig.set(...args)
}
+1 -1
View File
@@ -26,7 +26,7 @@ export default class ExceptionHandler {
logger.error(stack)
if (showDialog && app.isReady()) {
dialog.showErrorBox('系统错误', message)
dialog.showErrorBox('Error: ', message)
}
})
}
View File
+15 -16
View File
@@ -2,23 +2,22 @@
"menu": [
{
"label": "Motrix",
"id": "app",
"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" },
{ "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": "Services", "role": "services", "submenu": [] },
{ "label": "Hide Motrix", "role": "hide" },
{ "label": "Hide Others", "role": "hideothers" },
{ "label": "Show All", "role": "unhide" },
{ "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": "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"},
@@ -37,7 +36,7 @@
},
{
"label": "Edit",
"id": "edit",
"id": "menu.edit",
"submenu": [
{ "label": "Undo", "id": "edit.undo", "role": "undo" },
{ "label": "Redo", "id": "edit.redo", "role": "redo" },
@@ -52,21 +51,21 @@
{
"label": "Window",
"role": "window",
"id": "window",
"id": "menu.window",
"submenu": [
{ "label": "Reload", "id": "view.reload", "role": "reload" },
{ "label": "Close", "role": "close" },
{ "label": "Minimize", "role": "minimize" },
{ "label": "Zoom", "role": "zoom" },
{ "label": "Enter Full Screen", "role": "togglefullscreen" },
{ "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", "role": "front" }
{ "label": "Bring All to Front", "id": "window.front", "role": "front" }
]
},
{
"label": "Help",
"role": "help",
"id": "help",
"id": "menu.help",
"submenu": [
{ "label": "Motrix Website", "id": "help.official-website", "command": "help:official-website" },
{ "label": "Manual", "id": "help.manual", "command": "help:manual" },
+19 -20
View File
@@ -1,27 +1,26 @@
{
"menu": [
{
"label": "Motrix",
"id": "app",
"label": "File",
"id": "menu.file",
"submenu": [
{ "label": "About Motrix", "id": "app.about", "command": "application:about" },
{ "label": "About Motrix", "id": "app.about", "command": "application:about", "command-before": "application:show,index"},
{ "type": "separator" },
{ "label": "Preferences...", "id": "app.preferences", "command": "application:preferences" },
{ "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": "Services", "role": "services", "submenu": [] },
{ "label": "Hide Motrix", "role": "hide" },
{ "label": "Hide Others", "role": "hideothers" },
{ "label": "Show All", "role": "unhide" },
{ "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": "task",
"id": "menu.task",
"submenu": [
{ "label": "New Task", "id": "task.new-task", "command": "application:new-task", "command-arg": "uri" },
{ "label": "New BT Task", "id": "task.new-bt-task", "command": "application:new-bt-task", "command-arg": "torrent" },
{ "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" },
@@ -37,7 +36,7 @@
},
{
"label": "Edit",
"id": "edit",
"id": "menu.edit",
"submenu": [
{ "label": "Undo", "id": "edit.undo", "role": "undo" },
{ "label": "Redo", "id": "edit.redo", "role": "redo" },
@@ -52,21 +51,21 @@
{
"label": "Window",
"role": "window",
"id": "window",
"id": "menu.window",
"submenu": [
{ "label": "Reload", "id": "view.reload", "role": "reload" },
{ "label": "Close", "role": "close" },
{ "label": "Minimize", "role": "minimize" },
{ "label": "Zoom", "role": "zoom" },
{ "label": "Enter Full Screen", "role": "togglefullscreen" },
{ "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", "role": "front" }
{ "label": "Bring All to Front", "id": "window.front", "role": "front" }
]
},
{
"label": "Help",
"role": "help",
"id": "help",
"id": "menu.help",
"submenu": [
{ "label": "Motrix Website", "id": "help.official-website", "command": "help:official-website" },
{ "label": "Manual", "id": "help.manual", "command": "help:manual" },
+16 -17
View File
@@ -1,24 +1,23 @@
{
"menu": [
{
"label": "Motrix",
"id": "app",
"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" },
{ "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": "Services", "role": "services", "submenu": [] },
{ "label": "Hide Motrix", "role": "hide" },
{ "label": "Hide Others", "role": "hideothers" },
{ "label": "Show All", "role": "unhide" },
{ "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": "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"},
@@ -37,7 +36,7 @@
},
{
"label": "Edit",
"id": "edit",
"id": "menu.edit",
"submenu": [
{ "label": "Undo", "id": "edit.undo", "role": "undo" },
{ "label": "Redo", "id": "edit.redo", "role": "redo" },
@@ -52,21 +51,21 @@
{
"label": "Window",
"role": "window",
"id": "window",
"id": "menu.window",
"submenu": [
{ "label": "Reload", "id": "view.reload", "role": "reload" },
{ "label": "Close", "role": "close" },
{ "label": "Minimize", "role": "minimize" },
{ "label": "Zoom", "role": "zoom" },
{ "label": "Enter Full Screen", "role": "togglefullscreen" },
{ "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", "role": "front" }
{ "label": "Bring All to Front", "id": "window.front", "role": "front" }
]
},
{
"label": "Help",
"role": "help",
"id": "help",
"id": "menu.help",
"submenu": [
{ "label": "Motrix Website", "id": "help.official-website", "command": "help:official-website" },
{ "label": "Manual", "id": "help.manual", "command": "help:manual" },
+14 -15
View File
@@ -2,23 +2,22 @@
"menu": [
{
"label": "Motrix",
"id": "app",
"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": "服务", "role": "services", "submenu": [] },
{ "label": "隐藏 Motrix", "role": "hide" },
{ "label": "隐藏其他", "role": "hideothers" },
{ "label": "显示全部", "role": "unhide" },
{ "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": "task",
"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"},
@@ -37,7 +36,7 @@
},
{
"label": "编辑",
"id": "edit",
"id": "menu.edit",
"submenu": [
{ "label": "撤销", "id": "edit.undo", "role": "undo" },
{ "label": "重做", "id": "edit.redo", "role": "redo" },
@@ -52,21 +51,21 @@
{
"label": "窗口",
"role": "window",
"id": "window",
"id": "menu.window",
"submenu": [
{ "label": "重新加载", "id": "view.reload", "role": "reload" },
{ "label": "关闭", "role": "close" },
{ "label": "最小化", "role": "minimize" },
{ "label": "放大", "role": "zoom" },
{ "label": "进入全屏幕", "role": "togglefullscreen" },
{ "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": "前置全部窗口", "role": "front" }
{ "label": "前置全部窗口", "id": "window.front", "role": "front" }
]
},
{
"label": "帮助",
"role": "help",
"id": "help",
"id": "menu.help",
"submenu": [
{ "label": "Motrix 官网", "id": "help.official-website", "command": "help:official-website" },
{ "label": "使用手册", "id": "help.manual", "command": "help:manual" },
+18 -19
View File
@@ -1,27 +1,26 @@
{
"menu": [
{
"label": "Motrix",
"id": "app",
"label": "文件",
"id": "menu.file",
"submenu": [
{ "label": "关于 Motrix", "id": "app.about", "command": "application:about" },
{ "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": "服务", "role": "services", "submenu": [] },
{ "label": "隐藏 Motrix", "role": "hide" },
{ "label": "隐藏其他", "role": "hideothers" },
{ "label": "显示全部", "role": "unhide" },
{ "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": "task",
"id": "menu.task",
"submenu": [
{ "label": "新建任务", "id": "task.new-task", "command": "application:new-task" },
{ "label": "新建 BT 任务", "id": "task.new-bt-task", "command": "application:new-bt-task", "command-arg": "torrent" },
{ "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" },
@@ -37,7 +36,7 @@
},
{
"label": "编辑",
"id": "edit",
"id": "menu.edit",
"submenu": [
{ "label": "撤销", "id": "edit.undo", "role": "undo" },
{ "label": "重做", "id": "edit.redo", "role": "redo" },
@@ -52,21 +51,21 @@
{
"label": "窗口",
"role": "window",
"id": "window",
"id": "menu.window",
"submenu": [
{ "label": "重新加载", "id": "view.reload", "role": "reload" },
{ "label": "关闭", "role": "close" },
{ "label": "最小化", "role": "minimize" },
{ "label": "放大", "role": "zoom" },
{ "label": "进入全屏幕", "role": "togglefullscreen" },
{ "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": "前置全部窗口", "role": "front" }
{ "label": "前置全部窗口", "id": "window.front", "role": "front" }
]
},
{
"label": "帮助",
"role": "help",
"id": "help",
"id": "menu.help",
"submenu": [
{ "label": "Motrix 官网", "id": "help.official-website", "command": "help:official-website" },
{ "label": "使用手册", "id": "help.manual", "command": "help:manual" },
+15 -16
View File
@@ -1,24 +1,23 @@
{
"menu": [
{
"label": "Motrix",
"id": "app",
"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": "服务", "role": "services", "submenu": [] },
{ "label": "隐藏 Motrix", "role": "hide" },
{ "label": "隐藏其他", "role": "hideothers" },
{ "label": "显示全部", "role": "unhide" },
{ "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": "task",
"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"},
@@ -37,7 +36,7 @@
},
{
"label": "编辑",
"id": "edit",
"id": "menu.edit",
"submenu": [
{ "label": "撤销", "id": "edit.undo", "role": "undo" },
{ "label": "重做", "id": "edit.redo", "role": "redo" },
@@ -52,21 +51,21 @@
{
"label": "窗口",
"role": "window",
"id": "window",
"id": "menu.window",
"submenu": [
{ "label": "重新加载", "id": "view.reload", "role": "reload" },
{ "label": "关闭", "role": "close" },
{ "label": "最小化", "role": "minimize" },
{ "label": "放大", "role": "zoom" },
{ "label": "进入全屏幕", "role": "togglefullscreen" },
{ "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": "前置全部窗口", "role": "front" }
{ "label": "前置全部窗口", "id": "window.front", "role": "front" }
]
},
{
"label": "帮助",
"role": "help",
"id": "help",
"id": "menu.help",
"submenu": [
{ "label": "Motrix 官网", "id": "help.official-website", "command": "help:official-website" },
{ "label": "使用手册", "id": "help.manual", "command": "help:manual" },
+17 -3
View File
@@ -13,7 +13,7 @@ const defaultBrowserOptions = {
export default class WindowManager extends EventEmitter {
constructor (options = {}) {
super()
this.options = options
this.userConfig = options.userConfig || {}
this.windows = {}
@@ -28,8 +28,18 @@ export default class WindowManager extends EventEmitter {
this.willQuit = flag
}
getPageOptions (page) {
const result = pageConfig[page] || {}
const hideAppMenu = this.userConfig['hide-app-menu']
if (hideAppMenu) {
result.frame = false
}
return result
}
openWindow (page) {
const options = pageConfig[page] || {}
const options = this.getPageOptions(page)
let window = this.windows[page] || null
if (window) {
window.restore()
@@ -70,7 +80,11 @@ export default class WindowManager extends EventEmitter {
}
getWindows () {
return this.windows
return this.windows || {}
}
getWindowList () {
return Object.values(this.getWindows())
}
addWindow (page, window) {
+5 -2
View File
@@ -120,8 +120,11 @@ export default class Api {
uris,
options
} = params
const args = compactUndefined([uris, options])
return this.client.call('addUri', ...args)
const tasks = uris.map((uri) => {
const args = compactUndefined([[uri], options])
return [ 'aria2.addUri', ...args ]
})
return this.client.multicall(tasks)
}
addTorrent (params) {
+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12" width="12" height="12">
<g class="nc-icon-wrapper" stroke-width="1" fill="#111111" stroke="#111111">
<line x1="1.5" y1="1.5" x2="10.5" y2="10.5" fill="none" stroke="#111111" stroke-linecap="round" stroke-linejoin="round"/>
<line x1="10.5" y1="1.5" x2="1.5" y2="10.5" fill="none" stroke="#111111" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 429 B

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12" width="12" height="12">
<g class="nc-icon-wrapper" stroke-width="1" fill="#111111" stroke="#111111">
<polyline points="5.5 1.5 10.5 1.5 10.5 6.5" fill="none" stroke="#111111" stroke-linecap="round" stroke-linejoin="round"/>
<polyline points="1.5 5.5 1.5 10.5 6.5 10.5" fill="none" stroke-linecap="round" stroke-linejoin="round" data-color="color-2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 435 B

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12" width="12" height="12">
<g class="nc-icon-wrapper" stroke-width="1" fill="#111111" stroke="#111111">
<line x1="1" y1="6" x2="11" y2="6" fill="none" stroke="#111111" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 294 B

@@ -31,7 +31,6 @@
},
data () {
const version = this.$electron.remote.app.getVersion()
console.log('version===>', version)
return {
version
}
+1 -2
View File
@@ -3,11 +3,10 @@
<div class="app-version">
<mo-logo :width="93" :height="21" style="vertical-align: bottom;" />
<span>Version {{version}}</span>
<!-- <p>一款 macOS 全能下载工具</p> -->
</div>
<div class="app-icon"></div>
<div class="engine-info" v-if="!!engine">
<h4>引擎版本 {{engine.version}}</h4>
<h4>{{ $t('about.engine-version') }} {{engine.version}}</h4>
<ul v-if="!isMas()">
<li
v-for="(feature, index) in engine.enabledFeatures"
+5 -4
View File
@@ -7,10 +7,13 @@
</el-col>
<el-col :span="16" class="copyright-right">
<a target="_blank" href="https://motrix.app/about" rel="noopener noreferrer">
关于我们
{{ $t('about.about') }}
</a>
<a target="_blank" href="https://motrix.app/support" rel="noopener noreferrer">
帮助支持
{{ $t('about.support') }}
</a>
<a target="_blank" href="https://motrix.app/release" rel="noopener noreferrer">
{{ $t('about.release') }}
</a>
</el-col>
</el-row>
@@ -22,7 +25,6 @@
}
</script>
<style lang="scss">
.copyright {
width: 100%;
@@ -45,5 +47,4 @@
margin-left: 30px;
}
}
</style>
+2 -6
View File
@@ -24,7 +24,7 @@
<script>
import is from 'electron-is'
import { mapState, mapActions } from 'vuex'
import { mapState } from 'vuex'
import LogoMini from '@/components/Logo/LogoMini'
import '@/components/Icons/menu-task'
import '@/components/Icons/menu-add'
@@ -58,14 +58,10 @@
// }
},
nav (page) {
console.log('nav page===>', page)
this.$router.push({
path: page
})
},
...mapActions('app', [
'changeCurrentPage'
])
}
}
}
</script>
+12 -5
View File
@@ -1,8 +1,11 @@
import router from '@/router'
import store from '@/store'
import CommandManager from './CommandManager'
import { Message } from 'element-ui'
import { getLocaleManager } from '@/components/Locale'
const commands = new CommandManager()
const i18n = getLocaleManager().getI18n()
function showAboutPanel () {
store.dispatch('app/showAboutPanel')
@@ -20,24 +23,28 @@ function navigatePreferences () {
router.push({ path: '/preference' })
}
function pauseTask () {
function showUnderDevelopmentMessage () {
Message.info(i18n.t('app.under-development-message'))
}
function pauseTask () {
showUnderDevelopmentMessage()
}
function resumeTask () {
showUnderDevelopmentMessage()
}
function deleteTask () {
showUnderDevelopmentMessage()
}
function moveTaskUp () {
showUnderDevelopmentMessage()
}
function moveTaskDown () {
showUnderDevelopmentMessage()
}
function pauseAllTask () {
@@ -0,0 +1,16 @@
import Icon from '@/components/Icons/Icon'
Icon.register({
'win-close': {
'width': 12,
'height': 12,
'raw': `<line x1="1.5" y1="1.5" x2="10.5" y2="10.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
<line x1="10.5" y1="1.5" x2="1.5" y2="10.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>`,
'g': {
'stroke': 'currentColor',
'stroke-linecap': 'round',
'stroke-linejoin': 'round',
'stroke-width': '1'
}
}
})
@@ -0,0 +1,16 @@
import Icon from '@/components/Icons/Icon'
Icon.register({
'win-maximize': {
'width': 12,
'height': 12,
'raw': `<polyline points="5.5 1.5 10.5 1.5 10.5 6.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
<polyline points="1.5 5.5 1.5 10.5 6.5 10.5" fill="none" stroke-linecap="round" stroke-linejoin="round" />`,
'g': {
'stroke': 'currentColor',
'stroke-linecap': 'round',
'stroke-linejoin': 'round',
'stroke-width': '1'
}
}
})
@@ -0,0 +1,15 @@
import Icon from '@/components/Icons/Icon'
Icon.register({
'win-minimize': {
'width': 12,
'height': 12,
'raw': `<line x1="1" y1="6" x2="11" y2="6" fill="none" stroke-linecap="round" stroke-linejoin="round"/>`,
'g': {
'stroke': 'currentColor',
'stroke-linecap': 'round',
'stroke-linejoin': 'round',
'stroke-width': '1'
}
}
})
+32
View File
@@ -0,0 +1,32 @@
import i18next from 'i18next'
import { getLanguage } from '@shared/locales'
import resources from '@shared/locales/all'
export class LocaleManager {
constructor (options = {}) {
this.options = options
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
}
@@ -44,7 +44,8 @@
const [{ gid }] = event
api.fetchTaskItem({ gid })
.then((task) => {
const message = `开始下载 ${getTaskName(task)}`
const taskName = getTaskName(task)
const message = this.$t('task.download-start-message', { taskName })
this.$message.info(message)
})
},
@@ -53,7 +54,8 @@
const [{ gid }] = event
api.fetchTaskItem({ gid })
.then((task) => {
const message = `暂停下载 ${getTaskName(task)}`
const taskName = getTaskName(task)
const message = this.$t('task.download-pause-message', { taskName })
this.$message.info(message)
})
},
@@ -62,7 +64,8 @@
const [{ gid }] = event
api.fetchTaskItem({ gid })
.then((task) => {
const message = `${getTaskName(task)} 下载中止`
const taskName = getTaskName(task)
const message = this.$t('task.download-stop-message', { taskName })
this.$message.info(message)
})
},
@@ -71,7 +74,8 @@
const [{ gid }] = event
api.fetchTaskItem({ gid })
.then((task) => {
const message = `${getTaskName(task)} 下载发生错误`
const taskName = getTaskName(task)
const message = this.$t('task.download-error-message', { taskName })
this.$message.error(message)
})
},
@@ -104,15 +108,17 @@
addToRecentTask(task)
openDownloadDock(path)
const message = `${taskName} 下载完成`
const message = this.$t('task.download-complete-message', { taskName })
this.$message.success(message)
/* eslint-disable no-new */
const notify = new Notification('下载完成', {
const notify = new Notification(this.$t('task.download-complete-notify'), {
body: taskName
})
notify.onclick = () => {
showItemInFolder(path)
showItemInFolder(path, {
errorMsg: this.$t('task.file-not-exist')
})
}
},
showTaskErrorNotify: function (task) {
@@ -122,11 +128,11 @@
const taskName = getTaskName(task)
const message = `${taskName} 下载失败`
const message = this.$t('task.download-fail-message', { taskName })
this.$message.success(message)
/* eslint-disable no-new */
new Notification('下载失败', {
new Notification(this.$t('task.download-fail-notify'), {
body: taskName
})
},
@@ -21,7 +21,9 @@
if (!this.path) {
return
}
this.$electron.shell.showItemInFolder(this.path)
this.$electron.shell.showItemInFolder(this.path, {
errorMsg: this.$t('task.file-not-exist')
})
}
}
}
@@ -0,0 +1,68 @@
<template>
<div class="title-bar">
<ul v-if="showActions" class="window-actions">
<li @click="handleMinimize">
<mo-icon name="win-minimize" width="12" height="12" />
</li>
<li @click="handleMaximize">
<mo-icon name="win-maximize" width="12" height="12" />
</li>
<li @click="handleClose">
<mo-icon name="win-close" width="12" height="12" />
</li>
</ul>
</div>
</template>
<script>
import '@/components/Icons/win-minimize'
import '@/components/Icons/win-maximize'
import '@/components/Icons/win-close'
export default {
name: 'mo-title-bar',
props: {
showActions: {
type: Boolean
}
},
computed: {
win: function () {
return this.$electron.remote.getCurrentWindow()
}
},
methods: {
handleMinimize: function () {
this.win.minimize()
},
handleMaximize: function () {
if (this.win.isMaximized()) {
this.win.unmaximize()
} else {
this.win.maximize()
}
},
handleClose: function () {
this.win.close()
}
}
}
</script>
<style lang="scss">
.window-actions {
position: fixed;
top: 0;
right: 24px;
list-style: none;
padding: 0;
margin: 0;
> li {
float: left;
padding: 5px 10px;
&:hover {
background-color: $--titlebar-actions-active-background;
}
}
}
</style>
+22 -11
View File
@@ -14,31 +14,42 @@ export function getUserDownloadsPath () {
export function prettifyDir (dir) {
const downloads = getUserDownloadsPath()
const result = dir === downloads ? '下载' : dir
const result = dir === downloads ? 'Downloads' : dir
return result
}
export function showItemInFolder (fullPath) {
export function showItemInFolder (fullPath, { errorMsg }) {
if (!fullPath) {
return
}
const result = remote.shell.showItemInFolder(fullPath)
if (!result) {
Message.error('目标文件不存在或已删除')
if (!result && errorMsg) {
Message.error(errorMsg)
}
return result
}
export function moveTaskFilesToTrash (task) {
export function openItem (fullPath, { errorMsg }) {
if (!fullPath) {
return
}
const result = remote.shell.openItem(fullPath)
if (!result && errorMsg) {
Message.error(errorMsg)
}
return result
}
export function moveTaskFilesToTrash (task, { pathErrorMsg, delFailMsg, delConfigFailMsg }) {
const path = getTaskFullPath(task)
if (!path) {
Message.error('文件路径异常,请手动删除')
if (!path && pathErrorMsg) {
Message.error(pathErrorMsg)
return false
}
const deleteResult1 = remote.shell.moveItemToTrash(path)
if (!deleteResult1) {
Message.error('删除任务文件失败,请手动删除')
if (!deleteResult1 && delFailMsg) {
Message.error(delFailMsg)
}
let deleteResult2 = true
@@ -46,8 +57,8 @@ export function moveTaskFilesToTrash (task) {
const isExtraExist = existsSync(extraFilePath)
if (isExtraExist) {
deleteResult2 = remote.shell.moveItemToTrash(extraFilePath)
if (!deleteResult2) {
Message.error('删除任务配置文件失败,请手动删除')
if (!deleteResult2 && delConfigFailMsg) {
Message.error(delConfigFailMsg)
}
}
+59 -18
View File
@@ -6,15 +6,35 @@
<el-main class="panel-content">
<el-form
class="form-preference"
ref="basicForm"
ref="advancedForm"
label-position="right"
size="mini"
:model="form"
:rules="rules">
<el-form-item label="代理: " :label-width="formLabelWidth">
<el-form-item :label="`${$t('preferences.ui')}: `" :label-width="formLabelWidth">
<el-col class="form-item-sub" :span="16">
<el-select
v-model="form.locale"
@change="handleLocaleChange"
:placeholder="$t('preferences.change-language')">
<el-option
v-for="item in locales"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-col>
<el-col v-if="showHideAppMenuOption" class="form-item-sub" :span="16">
<el-checkbox v-model="form.hideAppMenu">
{{ $t('preferences.hide-app-menu') }}
</el-checkbox>
</el-col>
</el-form-item>
<el-form-item :label="`${$t('preferences.proxy')}: `" :label-width="formLabelWidth">
<el-switch
v-model="form.useProxy"
active-text="使用代理服务器"
:active-text="$t('preferences.use-proxy')"
@change="onUseProxyChange"
>
</el-switch>
@@ -28,9 +48,9 @@
</el-input>
</el-col>
</el-form-item>
<el-form-item label="开发者: " :label-width="formLabelWidth">
<el-form-item :label="`${$t('preferences.developer')}: `" :label-width="formLabelWidth">
<el-col class="form-item-sub" :span="24">
模拟用户代理
{{ $t('preferences.mock-user-agent') }}
<el-input
type="textarea"
:autosize="{ minRows: 2, maxRows: 3 }"
@@ -45,7 +65,7 @@
</el-button-group>
</el-col>
<el-col class="form-item-sub" :span="24">
应用日志路径
{{ $t('preferences.app-log-path') }}
<el-input placeholder="" disabled v-model="logPath">
<mo-show-in-folder
slot="append"
@@ -55,7 +75,7 @@
</el-input>
</el-col>
<el-col class="form-item-sub" :span="24">
下载会话记录
{{ $t('preferences.download-session-path') }}
<el-input placeholder="" disabled v-model="sessionPath">
<mo-show-in-folder
slot="append"
@@ -65,13 +85,13 @@
</el-input>
</el-col>
<el-col class="form-item-sub" :span="24">
<el-button plain type="danger" @click="() => onResetClick()">恢复初始设置</el-button>
<el-button plain type="danger" @click="() => onFactoryResetClick()">{{ $t('preferences.factory-reset') }}</el-button>
</el-col>
</el-form-item>
</el-form>
<div class="form-actions">
<el-button type="primary" @click="submitForm('basicForm')">保存并应用</el-button>
<el-button @click="resetForm('basicForm')">放弃</el-button>
<el-button type="primary" @click="submitForm('advancedForm')">{{ $t('preferences.save') }}</el-button>
<el-button @click="resetForm('advancedForm')">{{ $t('preferences.discard') }}</el-button>
</div>
</el-main>
</el-container>
@@ -82,15 +102,21 @@
import { mapState } from 'vuex'
import ShowInFolder from '@/components/Native/ShowInFolder'
import userAgentMap from '@shared/ua'
import { getLanguage } from '@shared/locales'
import { getLocaleManager } from '@/components/Locale'
const initialForm = (config) => {
const {
locale,
hideAppMenu,
useProxy,
allProxy,
allProxyBackup,
userAgent
} = config
const result = {
locale,
hideAppMenu,
useProxy,
allProxy,
allProxyBackup,
@@ -108,12 +134,26 @@
return {
formLabelWidth: '23%',
form: initialForm(this.$store.state.preference.config),
rules: {}
rules: {},
color: '#c00',
locales: [
{
value: 'zh-CN',
label: '🇨🇳 简体中文'
},
{
value: 'en-US',
label: '🇺🇸 English (US)'
}
]
}
},
computed: {
title: function () {
return '进阶设置'
return this.$t('preferences.advanced')
},
showHideAppMenuOption: function () {
return is.windows() || is.linux()
},
...mapState('preference', {
config: state => state.config,
@@ -122,34 +162,35 @@
})
},
watch: {
},
methods: {
isRenderer: is.renderer,
handleLocaleChange (locale) {
const lng = getLanguage(locale)
getLocaleManager().changeLanguage(lng)
this.$electron.ipcRenderer.send('command', 'application:change-locale', lng)
},
onUseProxyChange (flag) {
this.form.allProxy = flag ? this.form.allProxyBackup : ''
console.log('this.form.allProxy===>', flag, this.form.allProxy)
},
onAllProxyBackupChange (value) {
this.form.allProxy = value
},
changeUA (type) {
const ua = userAgentMap[type]
console.log('changeUA===>', ua)
if (!ua) {
return
}
this.form.userAgent = ua
},
onResetClick () {
onFactoryResetClick () {
this.$electron.remote.dialog.showMessageBox({
type: 'warning',
title: '恢复初始设置',
message: '你确定要恢复为初始设置吗?',
buttons: ['是', '否'],
buttons: [this.$t('app.yes'), this.$t('app.no')],
cancelId: 1
}, (buttonIndex) => {
// 点击的按钮是哪个按钮 0: 是, 1: 否
if (buttonIndex === 0) {
this.$electron.ipcRenderer.send('command', 'application:reset')
}
+15 -19
View File
@@ -11,12 +11,12 @@
size="mini"
:model="form"
:rules="rules">
<el-form-item label="启动: " :label-width="formLabelWidth">
<el-form-item :label="`${$t('preferences.startup')}: `" :label-width="formLabelWidth">
<el-checkbox v-model="form.resumeAllWhenAppLaunched">
启动后自动开始未完成任务
{{ $t('preferences.auto-resume-all') }}
</el-checkbox>
</el-form-item>
<el-form-item label="默认下载路径: " :label-width="formLabelWidth">
<el-form-item :label="`${$t('preferences.default-dir')}: `" :label-width="formLabelWidth">
<el-input placeholder="" v-model="downloadDir" :readonly="isMas()">
<mo-select-directory
v-if="isRenderer()"
@@ -25,50 +25,50 @@
/>
</el-input>
<div class="el-form-item__info" v-if="isMas()" style="margin-top: 8px;">
App Store 的沙箱权限限制默认下载路径建议设置为您的下载目录
{{ $t('preferences.mas-default-dir-tip') }}
</div>
</el-form-item>
<el-form-item label="任务管理: " :label-width="formLabelWidth">
<el-form-item :label="`${$t('preferences.task-manage')}: `" :label-width="formLabelWidth">
<el-col class="form-item-sub" :span="24">
同时下载的最大任务数
{{ $t('preferences.max-concurrent-downloads') }}
<el-input-number
v-model="form.maxConcurrentDownloads"
controls-position="right"
:min="1"
:max="10"
label="同时下载最大任务数">
:label="$t('preferences.max-concurrent-downloads')">
</el-input-number>
</el-col>
<el-col class="form-item-sub" :span="24">
单任务下载的线程数
{{ $t('preferences.max-connection-per-server') }}
<el-input-number
v-model="form.split"
controls-position="right"
:min="1"
:max="form.maxConnectionPerServer"
label="单任务下载线程数">
:label="$t('preferences.max-connection-per-server')">
</el-input-number>
</el-col>
<el-col class="form-item-sub" :span="24">
<el-checkbox v-model="form.continue">
断点续传
{{ $t('preferences.continue') }}
</el-checkbox>
</el-col>
<el-col class="form-item-sub" :span="24">
<el-checkbox v-model="form.newTaskShowDownloading">
新建任务后自动跳转到下载页面
{{ $t('preferences.new-task-show-downloading') }}
</el-checkbox>
</el-col>
<el-col class="form-item-sub" :span="24">
<el-checkbox v-model="form.taskNotification">
下载完成后通知
{{ $t('preferences.task-completed-notify') }}
</el-checkbox>
</el-col>
</el-form-item>
</el-form>
<div class="form-actions">
<el-button type="primary" @click="submitForm('basicForm')">保存并应用</el-button>
<el-button @click="resetForm('basicForm')">放弃</el-button>
<el-button type="primary" @click="submitForm('basicForm')">{{ $t('preferences.save') }}</el-button>
<el-button @click="resetForm('basicForm')">{{ $t('preferences.discard') }}</el-button>
</div>
</el-main>
</el-container>
@@ -90,13 +90,9 @@
taskNotification,
newTaskShowDownloading
} = config
console.log('initialForm===>', dir, split)
const result = {
dir,
split,
userAgent: '',
referer: '',
cookie: '',
continue: config.continue,
resumeAllWhenAppLaunched,
maxConcurrentDownloads,
@@ -121,7 +117,7 @@
},
computed: {
title: function () {
return '基础设置'
return this.$t('preferences.basic')
},
downloadDir: function () {
return prettifyDir(this.form.dir)
+3 -11
View File
@@ -11,19 +11,8 @@
export default {
name: 'mo-content-preference',
props: {
category: {
type: String
}
},
computed: {
title: function () {
const titles = {
'basic': '基础设置',
'advanced': '进阶设置',
'lab': '实验室'
}
return titles[this.category]
}
},
components: {
},
@@ -47,6 +36,9 @@
}
.form-item-sub {
margin-bottom: 12px;
&:last-of-type {
margin-bottom: 0;
}
a {
color: $--color-text-regular;
text-decoration: none;
+13 -11
View File
@@ -6,41 +6,43 @@
<el-main class="panel-content">
<el-form
class="form-preference"
ref="basicForm"
ref="labForm"
label-position="right"
size="mini"
:model="form"
:rules="rules">
<el-form-item :label-width="formLabelWidth">
<div class="el-form-item__error">启用实验特性可能造成应用崩溃或数据丢失请自行决定</div>
<div class="el-form-item__error">
{{ $t('preferences.lab-warning') }}
</div>
</el-form-item>
<el-form-item label="下载协议: " :label-width="formLabelWidth">
<el-form-item :label="`${$t('preferences.download-protocol')}: `" :label-width="formLabelWidth">
<el-col class="form-item-sub" :span="24">
<el-switch
v-model="form.enableEggFeatures"
active-text="支持更多下载协议"
:active-text="$t('preferences.support-more-download-protocols')"
>
</el-switch>
</el-col>
</el-form-item>
<el-form-item label="浏览器扩展: " :label-width="formLabelWidth">
<el-form-item :label="`${$t('preferences.browser-extensions')}: `" :label-width="formLabelWidth">
<el-col class="form-item-sub" :span="24">
<a target="_blank" href="https://motrix.app/release/BaiduExporter.zip" rel="noopener noreferrer">
百度网盘助手
{{ $t('preferences.baidu-exporter') }}
<mo-icon name="link" width="14" height="14" />
</a>
<div class="el-form-item__info" style="margin-top: 8px;">
社区提供的浏览器扩展不保证可用性
{{ $t('preferences.browser-extensions-tip') }}
<a target="_blank" href="https://motrix.app/extensions/baidu" rel="noopener noreferrer">
点此查看使用说明
{{ $t('preferences.baidu-exporter-help') }}
</a>
</div>
</el-col>
</el-form-item>
</el-form>
<div class="form-actions">
<el-button type="primary" @click="submitForm('basicForm')">保存并应用</el-button>
<el-button @click="resetForm('basicForm')">放弃</el-button>
<el-button type="primary" @click="submitForm('labForm')">{{ $t('preferences.save') }}</el-button>
<el-button @click="resetForm('labForm')">{{ $t('preferences.discard') }}</el-button>
</div>
</el-main>
</el-container>
@@ -74,7 +76,7 @@
},
computed: {
title: function () {
return '实验室'
return this.$t('preferences.lab')
},
...mapState('preference', {
config: state => state.config
-53
View File
@@ -5,19 +5,11 @@
</template>
<script>
// import { mapState, mapGetters } from 'vuex'
export default {
name: 'mo-subnav',
components: {
},
computed: {
// ...mapState('app', {
// currentPage: state => state.currentPage
// }),
// ...mapGetters('app', {
// title: 'currentPageTitle'
// })
},
methods: {
}
@@ -25,49 +17,4 @@
</script>
<style lang="scss">
.subnav-inner {
margin-top: 44px;
padding: 0 16px;
h3 {
font-size: 16px;
color: #071D43;
font-weight: normal;
line-height: 24px;
margin: 0 0 28px;
}
ul {
list-style: none;
padding: 0;
margin: 0;
user-select: none;
cursor: default;
li {
margin-bottom: 8px;
padding: 8px 10px;
font-size: 14px;
line-height: 20px;
border-radius: 3px;
cursor: pointer;
i, span {
vertical-align: middle;
display: inline-block;
}
&:hover, &.active {
background-color: #EAECF0;
i, span, svg {
color: $--subnav-active-text-color;
}
}
}
}
}
.subnav-icon {
padding: 2px;
height: 16px;
margin-right: 12px;
svg {
width: 16px;
height: 16px;
}
}
</style>
@@ -9,7 +9,7 @@
<i class="subnav-icon">
<mo-icon name='preference-basic' width="20" height="20" />
</i>
<span>基础设置</span>
<span>{{ $t('preferences.basic') }}</span>
</li>
<li
@click="() => nav('advanced')"
@@ -18,7 +18,7 @@
<i class="subnav-icon">
<mo-icon name='preference-advanced' width="20" height="20" />
</i>
<span>进阶设置</span>
<span>{{ $t('preferences.advanced') }}</span>
</li>
<li
@click="() => nav('lab')"
@@ -27,7 +27,7 @@
<i class="subnav-icon">
<mo-icon name='preference-lab' width="20" height="20" />
</i>
<span>实验室</span>
<span>{{ $t('preferences.lab') }}</span>
</li>
</ul>
</nav>
@@ -49,13 +49,12 @@
},
computed: {
title: function () {
return '偏好设置'
return this.$t('subnav.preferences')
}
},
methods: {
isMas: is.mas,
nav: function (category = 'basic') {
console.log('nav category===>', category)
this.$router.push({
path: `/preference/${category}`
})
@@ -9,7 +9,7 @@
<i class="subnav-icon">
<mo-icon name="task-start" width="20" height="20" />
</i>
<span>下载中</span>
<span>{{ $t('task.active') }}</span>
</li>
<li
@click="() => nav('waiting')"
@@ -18,7 +18,7 @@
<i class="subnav-icon">
<mo-icon name="task-pause" width="20" height="20" />
</i>
<span>已暂停</span>
<span>{{ $t('task.waiting') }}</span>
</li>
<li
@click="() => nav('stopped')"
@@ -27,7 +27,7 @@
<i class="subnav-icon">
<mo-icon name="task-stop" width="20" height="20" />
</i>
<span>已完成</span>
<span>{{ $t('task.stopped') }}</span>
</li>
</ul>
</nav>
@@ -48,12 +48,11 @@
},
computed: {
title: function () {
return '任务列表'
return this.$t('subnav.task-list')
}
},
methods: {
nav: function (status = 'active') {
console.log('nav status===>', status)
this.$router.push({
path: `/task/${status}`
})
+53 -33
View File
@@ -12,20 +12,21 @@
:model="form"
:rules="rules">
<el-tabs :value="type" @tab-click="handleTabClick">
<el-tab-pane label="链接任务" name="uri">
<el-tab-pane :label="$t('task.uri-task')" name="uri">
<el-form-item>
<el-input
ref="uri"
type="textarea"
:autosize="{ minRows: 3, maxRows: 5 }"
auto-complete="off"
placeholder="添加多个下载链接时,请确保每行只有一个链接"
:placeholder="$t('task.uri-task-tip')"
@change="handleUriChange"
v-model="form.uris">
</el-input>
</el-form-item>
</el-tab-pane>
<el-tab-pane
label="种子任务"
:label="$t('task.torrent-task')"
name="torrent"
v-if="iLoveEggFeatures"
>
@@ -38,13 +39,13 @@
</el-tabs>
<el-row :gutter="12">
<el-col :span="15">
<el-form-item label="文件名: " :label-width="formLabelWidth">
<el-input placeholder="请输入文件名" v-model="form.out">
<el-form-item :label="`${$t('task.task-out')}: `" :label-width="formLabelWidth">
<el-input :placeholder="$t('task.task-out-tip')" v-model="form.out">
</el-input>
</el-form-item>
</el-col>
<el-col :span="9">
<el-form-item label="下载线程: " :label-width="formLabelWidth">
<el-form-item :label="`${$t('task.task-split')}: `" :label-width="formLabelWidth">
<el-input-number
v-model="form.split"
@change="handleSplitChange"
@@ -52,12 +53,12 @@
:min="1"
:max="config.maxConnectionPerServer"
:value="config.split"
label="下载线程">
:label="$t('task.task-split')">
</el-input-number>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="存储路径: " :label-width="formLabelWidth">
<el-form-item :label="`${$t('task.task-dir')}: `" :label-width="formLabelWidth">
<el-input placeholder="" v-model="downloadDir" :readonly="isMas()">
<mo-select-directory
v-if="isRenderer()"
@@ -67,42 +68,42 @@
</el-input>
</el-form-item>
<div v-if="showAdvanced">
<el-form-item label="UA: " :label-width="formLabelWidth">
<el-form-item :label="`${$t('task.task-dir')}: `" :label-width="formLabelWidth">
<el-input
type="textarea"
:autosize="{ minRows: 2, maxRows: 3 }"
auto-complete="off"
placeholder="User-Agent"
:placeholder="$t('task.task-user-agent')"
v-model="form.userAgent">
</el-input>
</el-form-item>
<el-form-item label="Referer: " :label-width="formLabelWidth">
<el-form-item :label="`${$t('task.task-referer')}: `" :label-width="formLabelWidth">
<el-input
type="textarea"
:autosize="{ minRows: 2, maxRows: 3 }"
auto-complete="off"
placeholder="Referer"
:placeholder="$t('task.task-referer')"
v-model="form.referer">
</el-input>
</el-form-item>
<el-form-item label="Cookie: " :label-width="formLabelWidth">
<el-form-item :label="`${$t('task.task-cookie')}: `" :label-width="formLabelWidth">
<el-input
type="textarea"
:autosize="{ minRows: 2, maxRows: 3 }"
auto-complete="off"
placeholder="Cookie"
:placeholder="$t('task.task-cookie')"
v-model="form.cookie">
</el-input>
</el-form-item>
<el-form-item label="" :label-width="formLabelWidth">
<el-checkbox class="chk" v-model="form.newTaskShowDownloading">跳转到下载页面</el-checkbox>
<el-checkbox class="chk" v-model="form.newTaskShowDownloading">{{$t('task.navigate-to-downloading')}}</el-checkbox>
</el-form-item>
</div>
</el-form>
<div slot="footer" class="dialog-footer">
<el-checkbox class="chk" v-model="showAdvanced">显示高级选项</el-checkbox>
<el-button @click="handleCancel('taskForm')"> </el-button>
<el-button type="primary" @click="submitForm('taskForm')"> </el-button>
<el-checkbox class="chk" v-model="showAdvanced">{{$t('task.show-advanced-options')}}</el-checkbox>
<el-button @click="handleCancel('taskForm')">{{$t('app.cancel')}}</el-button>
<el-button type="primary" @click="submitForm('taskForm')">{{$t('app.submit')}}</el-button>
</div>
</el-dialog>
</template>
@@ -110,12 +111,16 @@
<script>
import is from 'electron-is'
import { mapState } from 'vuex'
import { isEmpty, compact } from 'lodash'
import { isEmpty } from 'lodash'
import SelectDirectory from '@/components/Native/SelectDirectory'
import SelectTorrent from '@/components/Task/SelectTorrent'
import { prettifyDir } from '@/components/Native/utils'
import '@/components/Icons/inbox'
import { splitTextRows, needCheckCopyright } from '@shared/utils'
import {
detectResource,
splitTaskLinks,
needCheckCopyright
} from '@shared/utils'
const initialForm = (state) => {
const { dir, split, newTaskShowDownloading } = state.preference.config
@@ -155,8 +160,7 @@
showAdvanced: false,
torrentName: '',
form: {},
rules: {
}
rules: {}
}
},
computed: {
@@ -195,11 +199,20 @@
handleOpen () {
this.form = initialForm(this.$store.state)
if (this.taskType === 'uri') {
this.autofillResourceLink()
setTimeout(() => {
this.$refs.uri && this.$refs.uri.focus()
}, 50)
}
},
autofillResourceLink () {
const content = this.$electron.clipboard.readText()
const hasResource = detectResource(content)
if (!hasResource) {
return
}
this.form.uris = content
},
handleClose (done) {
this.$store.dispatch('app/hideAddTaskDialog')
},
@@ -207,9 +220,20 @@
this.reset()
},
handleTabClick (tab, event) {
console.log(tab, tab.name, event)
this.$store.dispatch('app/changeAddTaskType', tab.name)
},
handleUriChange () {
// el-input does not support @paste event ?
// https://github.com/ElemeFE/element/blob/master/packages/input/src/input.vue
const { uris } = this.form
if (uris.includes('thunder://')) {
this.$message({
type: 'warning',
message: this.$t('task.thunder-link-tip'),
duration: 6000
})
}
},
handleTorrentChange (torrent, file, fileList) {
// TODO 种子选择部分文件下载
// console.log('handleTorrentChange===>', torrent, file, fileList)
@@ -270,7 +294,7 @@
},
buildUriPayload (form) {
let { uris } = form
uris = compact(splitTextRows(uris))
uris = splitTaskLinks(uris)
const options = this.buildOption(form)
const result = {
uris,
@@ -309,8 +333,7 @@
}
},
checkCopyright (type, form) {
let { uris } = form
uris = compact(splitTextRows(uris))
const { uris } = form
return new Promise((resolve, reject) => {
if (type !== 'uri') {
@@ -329,16 +352,15 @@
this.$electron.remote.dialog.showMessageBox({
type: 'warning',
title: '版权检查',
message: '您要下载的文件可能是有版权的音视频,请确保您有相应的版权方授权!',
buttons: ['是,我有版权方授权', '否'],
title: this.$t('task.copyright-warning'),
message: this.$t('task.copyright-warning-message'),
buttons: [this.$t('task.copyright-yes'), this.$t('task.copyright-no')],
cancelId: 1
}, (buttonIndex, checkboxChecked) => {
// 点击的按钮是哪个按钮 0: 是, 1: 否
if (buttonIndex === 0) {
resolve()
} else {
reject(new Error('因版权问题,添加任务失败'))
reject(new Error(this.$t('task.copyright-error-message')))
}
})
})
@@ -361,7 +383,6 @@
})
.catch((err) => {
this.$message.error(err.message)
// this.reset()
})
})
}
@@ -386,6 +407,5 @@
line-height: 28px;
}
}
}
</style>
+3 -3
View File
@@ -36,9 +36,9 @@
computed: {
title: function () {
const titles = {
'active': '下载中',
'waiting': '已暂停',
'stopped': '已完成'
'active': this.$t('task.active'),
'waiting': this.$t('task.waiting'),
'stopped': this.$t('task.stopped')
}
return titles[this.status]
}
@@ -9,7 +9,7 @@
:show-file-list="false">
<i class="upload-inbox-icon"><mo-icon name="inbox" width="24" height="24" /></i>
<div class="el-upload__text">
将种子拖到此处<em>点击选择</em>
{{ $t('task.select-torrent') }}
<div class="torrent-name" v-if="name">{{ name }}</div>
</div>
</el-upload>
@@ -59,9 +59,6 @@
</script>
<style lang="scss">
@import '../Theme/Variables';
@import '../Theme/Darkness/Variables';
.upload-torrent {
width: 100%;
.el-upload, .el-upload-dragger {
+11 -11
View File
@@ -1,21 +1,21 @@
<template>
<div class="task-actions">
<el-tooltip class="item" effect="dark" content="刷新列表" placement="bottom">
<el-tooltip class="item" effect="dark" :content="$t('task.refresh-list')" placement="bottom">
<i @click="onRefreshClick">
<mo-icon name="refresh" width="14" height="14" :spin="refreshing" />
</i>
</el-tooltip>
<el-tooltip class="item" effect="dark" content="恢复所有任务" placement="bottom">
<el-tooltip class="item" effect="dark" :content="$t('task.resume-all-task')" placement="bottom">
<i @click="onResumeAllClick">
<mo-icon name="task-start-line" width="14" height="14" />
</i>
</el-tooltip>
<el-tooltip class="item" effect="dark" content="暂停所有任务" placement="bottom">
<el-tooltip class="item" effect="dark" :content="$t('task.pause-all-task')" placement="bottom">
<i @click="onPauseAllClick">
<mo-icon name="task-pause-line" width="14" height="14" />
</i>
</el-tooltip>
<!-- <el-tooltip class="item" effect="dark" content="移除选中的任务" placement="bottom">
<!-- <el-tooltip class="item" effect="dark" :content="$t('task.delete-selected-tasks')" placement="bottom">
<i>
<mo-icon name="delete" width="14" height="14" />
</i>
@@ -23,7 +23,7 @@
<el-tooltip
class="item"
effect="dark"
content="清除已完成的任务"
:content="$t('task.purge-record')"
placement="bottom"
v-if="currentList === 'stopped'"
>
@@ -86,33 +86,33 @@
onResumeAllClick: function () {
this.$store.dispatch('task/resumeAllTask')
.then(() => {
this.$message.success(`恢复全部任务成功`)
this.$message.success(this.$t('task.resume-all-task-success'))
})
.catch(({ code }) => {
if (code === 1) {
this.$message.error(`恢复全部任务失败`)
this.$message.error(this.$t('task.resume-all-task-fail'))
}
})
},
onPauseAllClick: function () {
this.$store.dispatch('task/pauseAllTask')
.then(() => {
this.$message.success(`暂停全部任务成功`)
this.$message.success(this.$t('task.pause-all-task-success'))
})
.catch(({ code }) => {
if (code === 1) {
this.$message.error(`暂停全部任务失败`)
this.$message.error(this.$t('task.pause-all-task-fail'))
}
})
},
onPurgeRecordClick: function () {
this.$store.dispatch('task/purgeTaskRecord')
.then(() => {
this.$message.success(`移除全部下载记录成功`)
this.$message.success(this.$t('task.purge-record-success'))
})
.catch(({ code }) => {
if (code === 1) {
this.$message.error(`移除全部下载记录失败`)
this.$message.error(this.$t('task.purge-record-fail'))
}
})
}
+32 -6
View File
@@ -1,5 +1,5 @@
<template>
<li :key="task.gid" class="task-item" v-on:dblclick="toggleTask">
<li :key="task.gid" class="task-item" v-on:dblclick="onDbClick">
<div class="task-name" :title="taskName">
<span>{{ taskName }}</span>
</div>
@@ -17,7 +17,17 @@
<div v-if="task.status ==='active'">
<span>{{ task.downloadSpeed | bytesToSize }}/s</span>
<span>
{{ remaining | timeFormat('剩余') }}
{{
remaining | timeFormat({
prefix: $t('task.remaining-prefix'),
i18n: {
'gt1d': $t('app.gt1d'),
'hour': $t('app.hour'),
'minute': $t('app.minute'),
'second': $t('app.second')
}
})
}}
</span>
</div>
</el-col>
@@ -37,10 +47,14 @@
import '@/components/Icons/more'
import {
getTaskName,
getTaskFullPath,
timeRemaining,
bytesToSize,
timeFormat
} from '@shared/utils'
import {
openItem
} from '@/components/Native/utils'
export default {
name: 'mo-task-item',
@@ -55,7 +69,7 @@
},
computed: {
taskName: function () {
return getTaskName(this.task, '获取任务名中...')
return getTaskName(this.task, this.$t('task.get-task-name'))
},
remaining: function () {
const { totalLength, completedLength, downloadSpeed } = this.task
@@ -68,11 +82,23 @@
},
methods: {
getTaskName,
toggleTask () {
onDbClick () {
const { status } = this.task
if (['waiting', 'paused'].indexOf(status) === -1) {
return
if (status === 'complete') {
this.openTask()
} else if (['waiting', 'paused'].includes(status) !== -1) {
this.toggleTask()
}
},
openTask () {
const { taskName } = this
this.$message.info(this.$t('task.opening-task-message', { taskName }))
const fullPath = getTaskFullPath(this.task)
openItem(fullPath, {
errorMsg: this.$t('task.file-not-exist')
})
},
toggleTask () {
this.$store.dispatch('task/toggleTask', this.task)
}
}
@@ -1,8 +1,8 @@
<template>
<div class="task-item-actions" v-on:dblclick.stop="() => null">
<i @click.stop="onMoreClick">
<!-- <i @click.stop="onMoreClick">
<mo-icon name="more" width="14" height="14" />
</i>
</i> -->
<i @click.stop="onInfoClick" v-if="mode === 'LIST'">
<mo-icon name="info-circle" width="14" height="14" />
</i>
@@ -74,24 +74,30 @@
return getTaskFullPath(this.task)
}
},
filters: {
},
methods: {
isRenderer: is.renderer,
showConfirmBox: function () {
deleteTaskFiles: function (task) {
moveTaskFilesToTrash(task, {
pathErrorMsg: this.$t('task.file-path-error'),
delFailMsg: this.$t('task.remove-task-file-fail'),
delConfigFailMsg: this.$t('task.remove-task-config-file-fail')
})
},
removeTaskItem: function (task, isRemoveWithFiles) {
this.$store.dispatch('task/removeTask', this.task)
.then(() => {
if (isRemoveWithFiles) {
moveTaskFilesToTrash(task)
this.deleteTaskFiles(task)
}
this.$message.success(`移除任务「${this.taskName}」成功`)
this.$message.success(this.$t('task.delete-task-success', {
taskName: this.taskName
}))
})
.catch(({ code }) => {
if (code === 1) {
this.$message.error(`移除任务「${this.taskName}」失败`)
this.$message.error(this.$t('task.delete-task-fail', {
taskName: this.taskName
}))
}
})
},
@@ -99,35 +105,37 @@
this.$store.dispatch('task/removeTaskRecord', this.task)
.then(() => {
if (isRemoveWithFiles) {
moveTaskFilesToTrash(task)
this.deleteTaskFiles(task)
}
this.$message.success(`移除「${this.taskName}」下载记录成功`)
this.$message.success(this.$t('task.remove-record-success', {
taskName: this.taskName
}))
})
.catch(({ code }) => {
if (code === 1) {
this.$message.error(`移除「${this.taskName}」下载记录失败`)
this.$message.error(this.$t('task.remove-record-fail', {
taskName: this.taskName
}))
}
})
},
onResumeClick: function () {
this.$store.dispatch('task/resumeTask', this.task)
.then(() => {
this.$message.success(`恢复任务「${this.taskName}」成功`)
})
.catch(({ code }) => {
if (code === 1) {
this.$message.error(`恢复任务「${this.taskName}」失败`)
this.$message.error(this.$t('task.resume-task-fail', {
taskName: this.taskName
}))
}
})
},
onPauseClick: function () {
this.$store.dispatch('task/pauseTask', this.task)
.then(() => {
this.$message.success(`暂停任务「${this.taskName}」成功`)
})
.catch(({ code }) => {
if (code === 1) {
this.$message.error(`暂停任务「${this.taskName}」失败`)
this.$message.error(this.$t('task.pause-task-fail', {
taskName: this.taskName
}))
}
})
},
@@ -136,13 +144,12 @@
const { task } = this
this.$electron.remote.dialog.showMessageBox({
type: 'warning',
title: '移除任务',
message: `你确定要移除任务「${this.taskName}」吗?`,
buttons: ['是', '否'],
title: this.$t('task.delete-task'),
message: this.$t('task.delete-task-confirm', { taskName: this.taskName }),
buttons: [this.$t('app.yes'), this.$t('app.no')],
cancelId: 1,
checkboxLabel: '同时删除文件'
checkboxLabel: this.$t('task.delete-task-label')
}, (buttonIndex, checkboxChecked) => {
// 点击的按钮是哪个按钮 0: 是, 1: 否
if (buttonIndex === 0) {
self.removeTaskItem(task, checkboxChecked)
}
@@ -153,26 +160,27 @@
const { task } = this
this.$electron.remote.dialog.showMessageBox({
type: 'warning',
title: '移除下载记录',
message: `你确定要移除「${this.taskName}」下载记录吗?`,
buttons: ['是', '否'],
title: this.$t('task.remove-record'),
message: this.$t('task.remove-record-confirm', { taskName: this.taskName }),
buttons: [this.$t('app.yes'), this.$t('app.no')],
cancelId: 1,
checkboxLabel: '同时删除文件'
checkboxLabel: this.$t('task.remove-record-label')
}, (buttonIndex, checkboxChecked) => {
// 点击的按钮是哪个按钮 0: 是, 1: 否
if (buttonIndex === 0) {
self.removeTaskRecord(task, checkboxChecked)
}
})
},
onFolderClick: function () {
showItemInFolder(this.path)
showItemInFolder(this.path, {
errorMsg: this.$t('task.file-not-exist')
})
},
onLinkClick: function () {
const uri = getTaskUri(this.task)
clipboard.writeText(uri)
.then(() => {
this.$message.success('复制下载地址成功')
this.$message.success(this.$t('task.copy-link-success'))
})
},
onInfoClick: function () {
+13 -3
View File
@@ -26,7 +26,17 @@
<div v-if="task.status ==='active'">
<span>{{ task.downloadSpeed | bytesToSize }}/s</span>
<span>
{{ remaining | timeFormat('剩余') }}
{{
remaining | timeFormat({
prefix: $t('task.remaining-prefix'),
i18n: {
'gt1d': $t('app.gt1d'),
'hour': $t('app.hour'),
'minute': $t('app.minute'),
'second': $t('app.second')
}
})
}}
</span>
</div>
</el-col>
@@ -69,12 +79,12 @@
},
computed: {
taskName: function () {
return getTaskName(this.task, '获取任务名中...')
return getTaskName(this.task, this.$t('task.get-task-name'))
},
dialogTitle: function () {
const len = this.taskName.length
let title = len > 40 ? this.taskName.substr(0, 40) + '...' : this.taskName
return `${title} 详情`
return this.$t('task.task-info-dialog-title', { title })
},
remaining: function () {
const { totalLength, completedLength, downloadSpeed } = this.task
+1 -1
View File
@@ -4,7 +4,7 @@
</ul>
<div class="no-task" v-else>
<div class="no-task-inner">
当前没有下载任务
{{ $t('task.no-task') }}
</div>
</div>
</template>
+11
View File
@@ -28,7 +28,17 @@ img {
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,
@@ -38,6 +48,7 @@ img {
.draggable {
-webkit-app-region: drag;
-webkit-user-select: none;
}
.el-progress-bar__inner {
+1 -1
View File
@@ -41,7 +41,7 @@
h3 {
font-size: 16px;
color: #071D43;
color: $--subnav-title-color;
font-weight: normal;
line-height: 24px;
margin: 0 0 28px;
@@ -731,6 +731,7 @@ $--font-path: '~element-ui/lib/theme-chalk/fonts';
-------------------------- */
$--app-background: transparent !default;
// $--app-background: #fff !default;
$--titlebar-actions-active-background: #eee !default;
/* Aside
-------------------------- */
+10 -2
View File
@@ -1,6 +1,9 @@
<template>
<div id="app">
<div class="title-bar"></div>
<mo-title-bar
v-if="isRenderer()"
:showActions="showWindowActions"
/>
<router-view></router-view>
<mo-engine-client
:secret="rpcSecret"
@@ -11,6 +14,7 @@
<script>
import is from 'electron-is'
import TitleBar from '@/components/Native/TitleBar'
import EngineClient from '@/components/Native/EngineClient'
import Ipc from '@/components/Native/Ipc'
import { mapState } from 'vuex'
@@ -18,12 +22,16 @@
export default {
name: 'Motrix',
components: {
[TitleBar.name]: TitleBar,
[EngineClient.name]: EngineClient,
[Ipc.name]: Ipc
},
computed: {
...mapState('preference', {
rpcSecret: state => state.rpcSecret
showWindowActions: state => {
return (is.windows() || is.linux()) && state.config.hideAppMenu
},
rpcSecret: state => state.config.rpcSecret
})
},
methods: {
+52 -36
View File
@@ -1,47 +1,63 @@
import is from 'electron-is'
import Vue from 'vue'
import axios from 'axios'
import App from './App'
import VueI18Next from '@panter/vue-i18next'
import { sync } from 'vuex-router-sync'
import router from '@/router'
import store from '@/store'
import Element, { Loading } from 'element-ui'
import '../../components/Theme/Index.scss'
import Icon from '../../components/Icons/Icon'
import axios from 'axios'
import 'svg-innerhtml'
import is from 'electron-is'
if (is.renderer()) {
Vue.use(require('vue-electron'))
import App from './App'
import router from '@/router'
import store from '@/store'
import { getLocaleManager } from '@/components/Locale'
import Icon from '@/components/Icons/Icon'
import '@/components/Theme/Index.scss'
function init (config) {
if (is.renderer()) {
Vue.use(require('vue-electron'))
}
Vue.http = Vue.prototype.$http = axios
Vue.config.productionTip = false
const { locale } = config
const localeManager = getLocaleManager()
localeManager.changeLanguageByLocale(locale)
Vue.use(VueI18Next)
const i18n = new VueI18Next(localeManager.getI18n())
Vue.use(Element, {
size: 'mini',
i18n: (key, value) => i18n.t(key, value)
})
const loading = Loading.service({
fullscreen: true,
background: 'rgba(0, 0, 0, 0.1)'
})
Vue.component('mo-icon', Icon)
sync(store, router)
/* eslint-disable no-new */
window.app = new Vue({
components: { App },
router,
store,
i18n,
template: '<App/>'
}).$mount('#app')
setTimeout(() => {
loading.close()
}, 400)
}
Vue.http = Vue.prototype.$http = axios
Vue.config.productionTip = false
Vue.use(Element, { size: 'mini' })
Vue.component('mo-icon', Icon)
sync(store, router)
const loading = Loading.service({
fullscreen: true,
background: 'rgba(0, 0, 0, 0.1)'
})
store.dispatch('preference/fetchPreference')
.then(() => {
/* eslint-disable no-new */
window.app = new Vue({
components: { App },
router,
store,
template: '<App/>'
}).$mount('#app')
setTimeout(() => {
loading.close()
}, 400)
.then((config) => {
console.info('[Motrix] fetchPreference===>', config)
init(config)
})
.catch((err) => {
alert(err)
+13 -32
View File
@@ -12,7 +12,6 @@ const state = {
version: '',
enabledFeatures: []
},
engineStatus: '',
interval: BASE_INTERVAL,
stat: {
downloadSpeed: 0,
@@ -21,22 +20,11 @@ const state = {
numStopped: 0,
numWaiting: 0
},
currentPage: 'task',
addTaskVisible: false,
addTaskType: 'uri',
i18n: 'zh_CN'
}
const pageTitles = {
'task': '任务列表',
'preference': '偏好设置',
'about': '关于'
addTaskType: 'uri'
}
const getters = {
currentPageTitle: (state, getters) => {
return pageTitles[state.currentPage] ? pageTitles[state.currentPage] : ''
}
}
const mutations = {
@@ -49,9 +37,6 @@ const mutations = {
UPDATE_GLOBAL_STAT (state, stat) {
state.stat = stat
},
CHANGE_CURRENT_PAGE (state, currentPage) {
state.currentPage = currentPage
},
CHANGE_ADD_TASK_VISIBLE (state, visible) {
state.addTaskVisible = visible
},
@@ -70,19 +55,16 @@ const mutations = {
return
}
state.interval = interval
console.log('current interval===>', state.interval)
},
INCREASE_INTERVAL (state, millisecond) {
if (state.interval < MAX_INTERVAL) {
state.interval += millisecond
}
console.log('current interval===>', state.interval)
},
DECREASE_INTERVAL (state, millisecond) {
if (state.interval > MIN_INTERVAL) {
state.interval -= millisecond
}
console.log('current interval===>', state.interval)
}
}
@@ -107,8 +89,9 @@ const actions = {
stat[key] = Number(data[key])
})
if (stat.numActive > 0) {
const interval = BASE_INTERVAL - PER_INTERVAL * stat.numActive
const { numActive } = stat
if (numActive > 0) {
const interval = BASE_INTERVAL - PER_INTERVAL * numActive
dispatch('updateInterval', interval)
} else {
// fix downloadSpeed when numActive = 0
@@ -117,23 +100,21 @@ const actions = {
}
commit('UPDATE_GLOBAL_STAT', stat)
// @4ET
if (!is.renderer()) {
return
}
if (stat.numActive > 0) {
api.startPowerSaveBlocker()
} else {
api.stopPowerSaveBlocker()
if (is.renderer()) {
dispatch('togglePowerSaveBlocker', numActive)
}
})
},
togglePowerSaveBlocker (context, numActive) {
if (numActive > 0) {
api.startPowerSaveBlocker()
} else {
api.stopPowerSaveBlocker()
}
},
increaseInterval ({ commit }, millisecond = 100) {
commit('INCREASE_INTERVAL', millisecond)
},
changeCurrentPage ({ commit }, currentPage) {
commit('CHANGE_CURRENT_PAGE', currentPage)
},
showAddTaskDialog ({ commit }, taskType) {
commit('CHANGE_ADD_TASK_TYPE', taskType)
commit('CHANGE_ADD_TASK_VISIBLE', true)
-9
View File
@@ -7,16 +7,7 @@ const state = {
taskList: []
}
const listTitles = {
'active': '下载中',
'waiting': '已暂停',
'stopped': '已完成'
}
const getters = {
currentListTitle: (state, getters) => {
return listTitles[state.currentList] ? listTitles[state.currentList] : ''
}
}
const mutations = {
+2
View File
@@ -1,7 +1,9 @@
const userKeys = [
'locale',
'cookie',
'resume-all-when-app-launched',
'task-notification',
'hide-app-menu',
'new-task-show-downloading',
'use-proxy',
'all-proxy-backup',
+21
View File
@@ -0,0 +1,21 @@
import eleLocaleEn from 'element-ui/lib/locale/lang/en'
import eleLocaleZhCN from 'element-ui/lib/locale/lang/zh-CN'
import appLocaleEnUS from '@shared/locales/en-US'
import appLocaleZhCN from '@shared/locales/zh-CN'
const resources = {
'en-US': {
translation: {
...eleLocaleEn,
...appLocaleEnUS
}
},
'zh-CN': {
translation: {
...eleLocaleZhCN,
...appLocaleZhCN
}
}
}
export default resources
+17
View File
@@ -0,0 +1,17 @@
import appLocaleEnUS from '@shared/locales/en-US'
import appLocaleZhCN from '@shared/locales/zh-CN'
const resources = {
'en-US': {
translation: {
...appLocaleEnUS
}
},
'zh-CN': {
translation: {
...appLocaleZhCN
}
}
}
export default resources
+6
View File
@@ -0,0 +1,6 @@
export default {
'engine-version': 'Engine Version',
'about': 'About',
'release': 'Release',
'support': 'Support'
}
+20
View File
@@ -0,0 +1,20 @@
export default {
'task-list': 'Task List',
'add-task': 'Add Task',
'about': 'About Motrix',
'preferences': 'Preferences...',
'check-for-updates': 'Check for Updates...',
'hide': 'Hide Motrix',
'hide-others': 'Hide Others',
'unhide': 'Show All',
'quit': 'Quit Motrix',
'under-development-message': 'Sorry, this feature is under development...',
'yes': 'Yes',
'no': 'No',
'cancel': 'Cancel',
'submit': 'Submit',
'gt1d': '> 1 day',
'hour': 'H',
'minute': 'm',
'second': 's'
}
+9
View File
@@ -0,0 +1,9 @@
export default {
'undo': 'Undo',
'redo': 'Redo',
'cut': 'Cut',
'copy': 'Copy',
'paste': 'Paste',
'delete': 'Delete',
'select-all': 'Select All'
}
+7
View File
@@ -0,0 +1,7 @@
export default {
'official-website': 'Motrix Website',
'manual': 'Manual',
'release-notes': 'Release Notes...',
'report-problem': 'Report Problem',
'toggle-dev-tools': 'Toggle Developer Tools'
}
+21
View File
@@ -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
}
+8
View File
@@ -0,0 +1,8 @@
export default {
'app': 'Motrix',
'file': 'File',
'task': 'Task',
'edit': 'Edit',
'window': 'Window',
'help': 'Help'
}
+36
View File
@@ -0,0 +1,36 @@
export default {
'basic': 'Basic',
'advanced': 'Advanced',
'lab': 'Lab',
'save': 'Save & Apply',
'discard': 'Discard',
'startup': 'Startup',
'auto-resume-all': 'Auto resume all unfinished tasks',
'default-dir': 'Default Dir',
'mas-default-dir-tip': 'Due to the sandbox permissions restrictions of the App Store, the default download dir is recommended to be set to Downloads directory',
'task-manage': 'Task Manage',
'max-concurrent-downloads': 'Maximum active tasks',
'max-connection-per-server': 'Max connection per server',
'new-task-show-downloading': 'Auto show downloading after add task',
'continue': 'Continue',
'task-completed-notify': 'Notification after download is complete',
'auto-purge-record': 'Auto purge download record when app exit',
'ui': 'UI',
'language': 'Language',
'change-language': 'Change language',
'hide-app-menu': 'Hide App Menu (Windows & Linux Only)',
'proxy': 'Proxy',
'use-proxy': 'Enable Proxy',
'developer': 'Developer',
'mock-user-agent': 'Mock User-Agent',
'app-log-path': 'App log path',
'download-session-path': 'Download session path',
'factory-reset': 'Factory Reset',
'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',
'browser-extensions': 'Extensions',
'baidu-exporter': 'BaiduExporter',
'browser-extensions-tip': 'Provided by the community, ',
'baidu-exporter-help': 'Click here for usage'
}
+4
View File
@@ -0,0 +1,4 @@
export default {
'task-list': 'Tasks',
'preferences': 'Preferences'
}
+78
View File
@@ -0,0 +1,78 @@
export default {
'active': 'Downloading',
'waiting': 'Waiting',
'stopped': 'Stopped',
'new-task': 'New Task',
'new-bt-task': 'New BT Task',
'uri-task': 'URL',
'torrent-task': 'Torrent',
'uri-task-tip': 'One task url per line (support magnet)',
'thunder-link-tip': 'Tip: Thunder links may not be downloaded after decoding',
'task-name': 'Task Name',
'task-out': 'Rename',
'task-out-tip': 'Optional, support single task',
'task-split': 'Splits',
'task-dir': 'Dir',
'pause-task': 'Pause Task',
'task-ua': 'UA',
'task-user-agent': 'User-Agent',
'task-referer': 'Referer',
'task-cookie': 'Cookie',
'navigate-to-downloading': 'Navigate to Downloading',
'show-advanced-options': 'Advanced Options',
'copyright-warning': 'Copyright Warning',
'copyright-warning-message': 'The file you want to download may be copyrighted audio or video, please make sure you have the copyright license.',
'copyright-yes': 'Yes, I have',
'copyright-no': 'No',
'copyright-error-message': 'Adding task failed due to copyright issues',
'pause-task-success': 'Pause task "{{taskName}}" success',
'pause-task-fail': 'Pause task "{{taskName}}" fail',
'resume-task': 'Resume Task',
'resume-task-success': 'Resume task "{{taskName}}" success',
'resume-task-fail': 'Resume task "{{taskName}}" fail',
'delete-task': 'Delete Task',
'delete-selected-tasks': 'Delete Selected Tasks',
'delete-task-confirm': 'Are you sure to remove the "{{taskName}}" download task?',
'delete-task-label': 'Delete with Files',
'delete-task-success': 'Delete task "{{taskName}}" success',
'delete-task-fail': 'Delete task "{{taskName}}" fail',
'remove-task-file-fail': 'Failed to delete task file, please delete it manually',
'remove-task-config-file-fail': 'Failed to delete task config file, please delete it manually',
'move-task-up': 'Move Task Up',
'move-task-down': 'Move Task Down',
'pause-all-task': 'Pause All Task',
'pause-all-task-success': 'Pause all task success',
'pause-all-task-fail': 'Pause all task fail',
'resume-all-task': 'Resume All Task',
'resume-all-task-success': 'Resume all task success',
'resume-all-task-fail': 'Resume all task fail',
'clear-recent-tasks': 'Clear Recent Tasks',
'purge-record': 'Purge Task Record',
'purge-record-success': 'Purge task record success',
'purge-record-fail': 'Purge task record fail',
'refresh-list': 'Refresh Task List',
'no-task': 'There are no current downloads',
'copy-link': 'Copy Link',
'copy-link-success': 'Copy link success',
'remove-record': 'Remove Task Record',
'remove-record-confirm': 'Are you sure to remove the "{{taskName}}" download record?',
'remove-record-label': 'Delete with Files',
'remove-record-success': 'Remove task "{{taskName}}" record success',
'remove-record-fail': 'Remove task "{{taskName}}" record fail',
'show-in-folder': 'Show Task In Folder',
'file-not-exist': 'File does not exist or has been deleted',
'file-path-error': 'File path error',
'opening-task-message': 'Opening "{{taskName}}" ...',
'get-task-name': 'Get the task name...',
'remaining-prefix': 'Remaining',
'select-torrent': 'Drag the torrent here, or click to select',
'task-info-dialog-title': '{{title}} Detail',
'download-start-message': 'Start download {{taskName}}',
'download-pause-message': 'Pause download {{taskName}}',
'download-stop-message': '{{taskName}} download stopped',
'download-error-message': '{{taskName}} download error occurred',
'download-complete-message': '{{taskName}} download completed',
'download-complete-notify': 'Download Completed',
'download-fail-message': '{{taskName}} download failed',
'download-fail-notify': 'Download Failed'
}
+8
View File
@@ -0,0 +1,8 @@
export default {
'reload': 'Reload',
'close': 'Close',
'minimize': 'Minimize',
'zoom': 'Zoom',
'toggle-fullscreen': 'Enter Full Screen',
'front': 'Bring All to Front'
}
+28
View File
@@ -0,0 +1,28 @@
/**
* 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
*/
export const supportLanguages = [
'en-US',
'zh-CN'
]
/**
* getLanguage
* @param { String } locale
* https://electronjs.org/docs/api/locales
*/
export function getLanguage (locale = 'en-US') {
if (supportLanguages.includes(locale)) {
return locale
}
if (locale.startsWith('en')) {
return 'en-US'
}
if (locale.startsWith('zh')) {
return 'zh-CN'
}
}
+6
View File
@@ -0,0 +1,6 @@
export default {
'engine-version': '引擎版本',
'about': '关于我们',
'release': '更新日志',
'support': '帮助支持'
}
+20
View File
@@ -0,0 +1,20 @@
export default {
'task-list': '任务列表',
'add-task': '新建任务',
'about': '关于 Motrix',
'preferences': '偏好设置...',
'check-for-updates': '检查更新...',
'hide': '隐藏 Motrix',
'hide-others': '隐藏其他',
'unhide': '显示全部',
'quit': '退出 Motrix',
'under-development-message': '该功能开发中...',
'yes': '是',
'no': '否',
'cancel': '取 消',
'submit': '提 交',
'gt1d': '超过一天',
'hour': '时',
'minute': '分',
'second': '秒'
}
+9
View File
@@ -0,0 +1,9 @@
export default {
'undo': '撤销',
'redo': '重做',
'cut': '剪切',
'copy': '复制',
'paste': '黏贴',
'delete': '删除',
'select-all': '全选'
}
+7
View File
@@ -0,0 +1,7 @@
export default {
'official-website': 'Motrix 官网',
'manual': '使用手册',
'release-notes': '发行说明...',
'report-problem': '报告问题',
'toggle-dev-tools': '开发者工具'
}
+21
View File
@@ -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
}
+8
View File
@@ -0,0 +1,8 @@
export default {
'app': 'Motrix',
'file': '文件',
'task': '任务',
'edit': '编辑',
'window': '窗口',
'help': '帮助'
}
+36
View File
@@ -0,0 +1,36 @@
export default {
'basic': '基础设置',
'advanced': '进阶设置',
'lab': '实验室',
'save': '保存并应用',
'discard': '放弃',
'startup': '启动',
'auto-resume-all': '启动后自动开始未完成任务',
'default-dir': '默认下载路径',
'mas-default-dir-tip': '因 App Store 的沙箱权限限制,默认下载路径建议设置为您的「下载」目录',
'task-manage': '任务管理',
'max-concurrent-downloads': '同时下载的最大任务数',
'max-connection-per-server': '每个服务器最大连接数',
'new-task-show-downloading': '新建任务后自动跳转到下载页面',
'continue': '断点续传',
'task-completed-notify': '下载完成后通知',
'auto-purge-record': '当应用退出时自动清除下载记录',
'ui': '界面',
'language': '语言',
'change-language': '切换语言',
'hide-app-menu': '隐藏菜单栏(仅支持 Windows 和 Linux',
'proxy': '代理',
'use-proxy': '使用代理服务器',
'developer': '开发者',
'mock-user-agent': '模拟用户代理(UA',
'app-log-path': '应用日志路径',
'download-session-path': '应用日志路径',
'factory-reset': '恢复初始设置',
'lab-warning': '⚠️启用实验特性可能造成应用崩溃或数据丢失,请自行决定!',
'download-protocol': '下载协议',
'support-more-download-protocols': '支持更多下载协议',
'browser-extensions': '浏览器扩展',
'baidu-exporter': '百度网盘助手',
'browser-extensions-tip': '社区提供的浏览器扩展「不保证可用性」,',
'baidu-exporter-help': '点此查看使用说明'
}
+4
View File
@@ -0,0 +1,4 @@
export default {
'task-list': '任务列表',
'preferences': '偏好设置'
}
+78
View File
@@ -0,0 +1,78 @@
export default {
'active': '下载中',
'waiting': '等待中',
'stopped': '已停止',
'new-task': '新建任务',
'new-bt-task': '新建 BT 任务',
'uri-task': '链接任务',
'torrent-task': '种子任务',
'uri-task-tip': '添加多个下载链接时,请确保每行只有一个链接(支持磁力链)',
'thunder-link-tip': '友情提示:迅雷链接解码之后的资源不一定存在',
'task-name': '任务名',
'task-out': '重命名',
'task-out-tip': '选填(仅支持单任务)',
'task-split': '下载线程',
'task-dir': '存储路径',
'task-ua': 'UA',
'task-user-agent': 'User-Agent',
'task-referer': 'Referer',
'task-cookie': 'Cookie',
'navigate-to-downloading': '跳转到下载页面',
'show-advanced-options': '高级选项',
'copyright-warning': '版权提醒',
'copyright-warning-message': '您要下载的文件可能是有版权的音视频,请确保您有相应的版权方授权。',
'copyright-yes': '是,我有版权方授权',
'copyright-no': '否',
'copyright-error-message': '因版权问题,添加任务失败',
'pause-task': '暂停任务',
'pause-task-success': '暂停任务 "{{taskName}}" 成功',
'pause-task-fail': '暂停任务 "{{taskName}}" 失败',
'resume-task': '恢复任务',
'resume-task-success': '恢复任务 "{{taskName}}" 成功',
'resume-task-fail': '恢复任务 "{{taskName}}" 失败',
'delete-task': '移除任务',
'delete-selected-tasks': '移除选中的任务',
'delete-task-confirm': '你确定要移除 "{{taskName}}" 下载记录吗?',
'delete-task-label': '同时删除文件',
'delete-task-success': '移除任务 "{{taskName}}" 成功',
'delete-task-fail': '移除任务 "{{taskName}}" 失败',
'remove-task-file-fail': '删除任务文件失败,请手动删除',
'remove-task-config-file-fail': '删除任务配置文件失败,请手动删除',
'move-task-up': '上移任务',
'move-task-down': '下载任务',
'pause-all-task': '暂停所有任务',
'pause-all-task-success': '暂停所有任务成功',
'pause-all-task-fail': '暂停所有任务失败',
'resume-all-task': '恢复所有任务',
'resume-all-task-success': '恢复所有任务成功',
'resume-all-task-fail': '恢复所有任务失败',
'clear-recent-tasks': '清除最近的下载记录',
'purge-record': '清除下载记录',
'purge-record-success': '清除下载记录成功',
'purge-record-fail': '清除下载记录失败',
'refresh-list': '刷新任务列表',
'no-task': '当前没有下载任务',
'copy-link': '拷贝链接',
'copy-link-success': '拷贝链接成功',
'remove-record': '移除下载记录',
'remove-record-confirm': '你确定要移除 "{{taskName}}" 下载记录吗?',
'remove-record-label': '同时删除文件',
'remove-record-success': '移除 "{{taskName}}" 下载记录成功',
'remove-record-fail': '移除 "{{taskName}}" 下载记录失败',
'show-in-folder': '在文件夹中显示',
'file-not-exist': '目标文件不存在或已删除',
'file-path-error': '文件路径异常',
'opening-task-message': '正在打开 "{{taskName}}" ...',
'get-task-name': '获取任务名中...',
'remaining-prefix': '剩余',
'select-torrent': '将种子拖到此处,或点击选择',
'task-info-dialog-title': '{{title}} 详情',
'download-start-message': '开始下载 {{taskName}}',
'download-pause-message': '暂停下载 {{taskName}}',
'download-stop-message': '{{taskName}} 下载中止',
'download-error-message': '{{taskName}} 下载发生错误',
'download-complete-message': '{{taskName}} 下载完成',
'download-complete-notify': '下载完成',
'download-fail-message': '{{taskName}} 下载失败',
'download-fail-notify': '下载失败'
}
+8
View File
@@ -0,0 +1,8 @@
export default {
'reload': '重新加载',
'close': '关闭',
'minimize': '最小化',
'zoom': '放大',
'toggle-fullscreen': '进入全屏幕',
'front': '前置全部窗口'
}
+55 -8
View File
@@ -1,6 +1,7 @@
import {
isEmpty,
isNaN,
compact,
parseInt,
isFunction,
camelCase,
@@ -33,27 +34,47 @@ export function timeRemaining (totalLength, completedLength, downloadSpeed) {
return Math.ceil(remainingLength / downloadSpeed)
}
export function timeFormat (seconds, prefix = '', suffix = '') {
/**
* timeFormat
* @param {int} seconds
* @param {string} prefix
* @param {string} suffix
* @param {object} i18n
* i18n: {
* gt1d: 'More than one day',
* hour: 'H',
* minute: 'm',
* second: 's'
* }
*/
export function timeFormat (seconds, { prefix = '', suffix = '', i18n }) {
let result = ''
let hours = ''
let minutes = ''
let secs = seconds || 0
const i = {
gt1d: '> 1 day',
hour: 'H',
minute: 'm',
second: 's',
...i18n
}
if (secs <= 0) {
return ''
}
if (secs > 86400) {
return `${prefix} 超过一天 ${suffix}`
return `${prefix} ${i.gt1d} ${suffix}`
}
if (secs > 3600) {
hours = `${Math.floor(secs / 3600)} `
hours = `${Math.floor(secs / 3600)}${i.hour} `
secs %= 3600
}
if (secs > 60) {
minutes = `${Math.floor(secs / 60)} `
minutes = `${Math.floor(secs / 60)}${i.minute} `
secs %= 60
}
secs += '秒'
secs += i.second
result = hours + minutes + secs
return result ? `${prefix} ${result} ${suffix}` : result
}
@@ -83,7 +104,7 @@ export function getTaskName (task, defaultName = '') {
}
}
if (cnt > 1) {
result += ` (${cnt} 文件...)`
result += ` (${cnt} / ${files.length})`
}
}
@@ -264,11 +285,11 @@ export function isAudioOrVideo (uri = '') {
const result = suffixs.some((suffix) => {
return uri.includes(suffix)
})
console.warn('isAudioOrVideo===>', result)
return result
}
export function needCheckCopyright (uris) {
export function needCheckCopyright (links = '') {
const uris = splitTaskLinks(links)
const avs = uris.filter(uri => {
return isAudioOrVideo(uri)
})
@@ -276,3 +297,29 @@ export function needCheckCopyright (uris) {
const result = avs.length > 0
return result
}
export function decodeThunderLink (url = '') {
if (!url.startsWith('thunder://')) {
return url
}
let result = url.split('thunder://')[1]
result = Buffer.from(result, 'base64').toString('utf8')
result = result.substring(0, result.length - 2)
return result
}
export function splitTaskLinks (links = '') {
const temp = compact(splitTextRows(links))
const result = temp.map((item) => {
return decodeThunderLink(item)
})
return result
}
const resourceTag = ['http://', 'https://', 'ftp://', 'magnet:', 'thunder://']
export function detectResource (content) {
return resourceTag.some((type) => {
return content.includes(type)
})
}