commit 0b9b3d487860e6817ab348e3d24e1412613cebe7 Author: mattuy Date: Sun Jun 7 23:17:01 2020 +0800 first version commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..554f601 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.vscode +# Dependency directory +node_modules + +# Ignore built ts files +/bin/ +dist/**/* diff --git a/LICENCE b/LICENCE new file mode 100644 index 0000000..54090fd --- /dev/null +++ b/LICENCE @@ -0,0 +1 @@ +本程序仅用于学习交流,禁止任何个人、组织用于任何其它目的。对于使用本程序造成的任何后果,本程序不承担任何责任。 diff --git a/README.md b/README.md new file mode 100644 index 0000000..59f4d69 --- /dev/null +++ b/README.md @@ -0,0 +1,84 @@ +# Google Translate Desktop +Google Translate网页版的封装,通过[Electron](https://www.electronjs.org)构建。 + +首先说一下建立此仓库的目的。平时写代码经常需要查词,尝试了很多翻译软件,它们都很棒,但总是有些细节让人抓狂。或许作为一个翻译软件它们并没有什么问题,但在我个人的使用条件下,它们无法满足我的需求。 + +下面是我用过的软件,以及它们为什么不继续使用: +* 任何网页版翻译:需要打开浏览器,太慢 +* 金山词霸:不支持DPI自适应,太丑(现在不知道支不支持) +* 有道翻译:关键时刻掉链子,经常需要等待一会才能得到结果。划词窗口偶尔卡半天才出来。最致命的是MINI窗口经常不能自动处于输入状态,得鼠标点一下,大大降低了效率 +* Micosoft Translator:启动太慢,又不支持mini窗口。不支持开机自启动。如果一直保持打开得忍受任务栏多出一项,这对于某些强迫症患者(我)来说是难以忍受的 + +于是我有了使用Electron封装一个网页版翻译的想法,对比之下Google翻译似乎比微软翻译出结果快那么一点点,于是决定封装Google翻译。需要说明的是,我测试的是translate.google.cn,至于google.com没试...I am in China🙃 + +封装Google翻译的目的是用于写代码时快速查词,就这一个单纯的目的。因此它的功能可以很简单,但必须具备一些必要的功能,另外使用它可能需要忍受一些事情: +* 功能简陋 +* 必须联网 +* 自定义程度低,配置得直接修改配置文件 +* 只能在Windows上用(用到了Windows系统API) +* 在Google Translate页面完全加载前Mini窗口不会自动获取焦点,而这可能需要等待好几十秒 + + +## 特性 +* 支持主窗口最小化到托盘; +* 允许配置快捷键打开Mini窗口; +* 允许配置默认主窗口尺寸; +* Mini窗口自动获取输入焦点; +* 支持开机启动; + +* 不支持离线使用; +* 不支持取词划词; +* 未测试Windows之外的平台; + +对于Mini窗口自动获取输入焦点,由于是通过`dom-ready`事件注入JavaScript实现,因此在`dom-ready`之前Mini窗口无法自动获取焦点。而这需要大概十几秒,因为`translate.google.cn`尝试从`google.com`获取一些资源,而访问google.com会等待超时后失败(国内环境),但这些资源并不是完成翻译功能所必须的,因此并不影响翻译功能的使用。但未完成的非ajax请求会让`dom-ready`事件迟迟不能触发,导致依赖此事件注入JavaScript的代码直到请求超时后才执行。 +但这只在程序启动时发生,个人认为勉强能够忍受,就没有再折腾。如果有必要,或许可以通过`ServiceWorker`拦截? + +对于封装的url,本程序仅对translate.google.cn做了样式微调,如果换成其它的url,可能需要自行调整样式。配置项中允许更改url参数来加载其他网页。如果需要,还可以通过提供额外CSS来调整样式,它们将被注入页面,见[配置项](##配置项)。 +注意,你可能需要为你的样式加上!important标记以覆盖更高优先级的原始样式,因为CSS以嵌入式CSS的方式插入。 + + +## 实现 +通过Electron简单的封装https://translate.google.cn作为主窗口。 + +### Mini窗口 +Mini窗口的大小是固定的,想要修改只能修改代码。为了在更小区域呈现界面,本程序通过注入css隐藏了Mini窗口的Google Translate头部,还做了一些微调以减小其尺寸。 + +## 使用 +克隆本仓库到本地,然后执行`npm install`。 + +### 运行 +`npm start` + +### 打包 +`npm run package` + +通过`electron-packager`进行打包。当然您也可以使用其它Electron打包工具,例如[electron-builder](https://github.com/electron-userland/electron-builder)。但请劳烦您自行配置。 + + +## 配置项 + +配置文件只能是运行目录下的`config.json`。修改配置可能需要重启程序以应用修改。 + +| 配置名称 | 类型 | 默认值 | 备注 | +| ----------------------- | ------- | --------------------------- | +| mainWindowWidth | number | 1024 | 主窗口宽 +| mainWindowHeight | number | 586 | 主窗口高 +| url | string | https://translate.google.cn | 加载的url,其它地址没测试过 +| autoStart | boolean | false | 开机自启动 +| miniWindowEnabled | boolean | true | 启用Mini窗口快捷键 +| miniShortcut | string | CmdOrCtrl+Alt+M | 设置Mini窗口快捷键 +| extraCssForMain | string | "" | 额外插入主窗口的CSS +| extraCssForMini | string | "" | 额外插入Mini窗口的的CSS +| minimizeToTrayWhenClose | boolean | true | 关闭主窗口时最小化到托盘 +| minimizeToTrayWenStart | boolean | true | 启动时自动隐藏主窗口 + + +## 使用截图 + +主窗口 + +主窗口-有内容 + +迷你窗口-有内容 + +迷你窗口-有内容 diff --git a/appicon.ico b/appicon.ico new file mode 100644 index 0000000..eafa8f0 Binary files /dev/null and b/appicon.ico differ diff --git a/blob/main-input.png b/blob/main-input.png new file mode 100644 index 0000000..3d932d0 Binary files /dev/null and b/blob/main-input.png differ diff --git a/blob/main.png b/blob/main.png new file mode 100644 index 0000000..6311bd2 Binary files /dev/null and b/blob/main.png differ diff --git a/blob/mini-input.png b/blob/mini-input.png new file mode 100644 index 0000000..f0b50cf Binary files /dev/null and b/blob/mini-input.png differ diff --git a/blob/mini.png b/blob/mini.png new file mode 100644 index 0000000..a3a808d Binary files /dev/null and b/blob/mini.png differ diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..43b9b73 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1408 @@ +{ + "name": "google-translate-electron", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@electron/get": { + "version": "1.12.2", + "resolved": "https://registry.npm.taobao.org/@electron/get/download/@electron/get-1.12.2.tgz", + "integrity": "sha1-ZEIGavuZvgjO+5ooHktGkrM3ZPM=", + "requires": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "global-agent": "^2.0.2", + "global-tunnel-ng": "^2.7.1", + "got": "^9.6.0", + "progress": "^2.0.3", + "sanitize-filename": "^1.6.2", + "sumchecker": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz?cache=0&sync_timestamp=1589881689076&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-4.1.1.tgz", + "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", + "requires": { + "ms": "^2.1.1" + } + }, + "env-paths": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/env-paths/download/env-paths-2.2.0.tgz", + "integrity": "sha1-zcpVfcAJFSkX1hZuL+vh8DloXkM=" + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npm.taobao.org/fs-extra/download/fs-extra-8.1.0.tgz", + "integrity": "sha1-SdQ8RaiM2Wd2aMt74bRu/bjS4cA=", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/sumchecker/download/sumchecker-3.0.1.tgz", + "integrity": "sha1-Y3fplnlauwttNI6bPh37JDRajkI=", + "requires": { + "debug": "^4.1.0" + } + } + } + }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npm.taobao.org/@sindresorhus/is/download/@sindresorhus/is-0.14.0.tgz", + "integrity": "sha1-n7OjzzEyMoFR81PeRjLgHlIQK+o=" + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/@szmarczak/http-timer/download/@szmarczak/http-timer-1.1.2.tgz", + "integrity": "sha1-sWZeLEYaLNkvTBu/UNVFTeDUtCE=", + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@types/glob": { + "version": "7.1.2", + "resolved": "https://registry.npm.taobao.org/@types/glob/download/@types/glob-7.1.2.tgz", + "integrity": "sha1-BsomUhNTpUXZSgrcdPOKWdIyyYc=", + "dev": true, + "optional": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/lodash": { + "version": "4.14.155", + "resolved": "https://registry.npm.taobao.org/@types/lodash/download/@types/lodash-4.14.155.tgz?cache=0&sync_timestamp=1591198414262&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Flodash%2Fdownload%2F%40types%2Flodash-4.14.155.tgz", + "integrity": "sha1-4rRRT0aiYf0RVC5HUZwg6857wjo=", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npm.taobao.org/@types/minimatch/download/@types/minimatch-3.0.3.tgz", + "integrity": "sha1-PcoOPzOyAPx9ETnAzZbBJoyt/Z0=", + "dev": true, + "optional": true + }, + "@types/node": { + "version": "10.14.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.12.tgz", + "integrity": "sha512-QcAKpaO6nhHLlxWBvpc4WeLrTvPqlHOvaj0s5GriKkA1zq+bsFBPpfYCvQhLqLgYlIko8A9YrPdaMHCo5mBcpg==", + "dev": true, + "optional": true + }, + "asar": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/asar/download/asar-2.1.0.tgz", + "integrity": "sha1-l8alcECMTjihjUo/t0imIbWnhE4=", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "chromium-pickle-js": "^0.2.0", + "commander": "^2.20.0", + "cuint": "^0.2.2", + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "tmp-promise": "^1.0.5" + } + }, + "author-regex": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/author-regex/download/author-regex-1.0.0.tgz", + "integrity": "sha1-0IiFvmubv5Q5/gh8dihyRfCoFFA=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npm.taobao.org/base64-js/download/base64-js-1.3.1.tgz", + "integrity": "sha1-WOzoy3XdB+ce0IxzarxfrE2/jfE=", + "dev": true + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npm.taobao.org/bluebird/download/bluebird-3.7.2.tgz", + "integrity": "sha1-nyKcFb4nJFT/qXOs4NvueaGww28=", + "dev": true + }, + "boolean": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/boolean/download/boolean-3.0.1.tgz", + "integrity": "sha1-NezytKLuGRsLRJhvFOtfBSpcu08=", + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz", + "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/buffer-alloc/download/buffer-alloc-1.2.0.tgz", + "integrity": "sha1-iQ3ZDZI6hz4I4Q5f1RpX5bfM4Ow=", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/buffer-alloc-unsafe/download/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha1-vX3CauKXLQ7aJTvgYdupkjScGfA=", + "dev": true + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npm.taobao.org/buffer-crc32/download/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/buffer-fill/download/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/buffer-from/download/buffer-from-1.1.1.tgz", + "integrity": "sha1-MnE7wCj3XAL9txDXx7zsHyxgcO8=" + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npm.taobao.org/cacheable-request/download/cacheable-request-6.1.0.tgz?cache=0&sync_timestamp=1579607091967&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcacheable-request%2Fdownload%2Fcacheable-request-6.1.0.tgz", + "integrity": "sha1-IP+4vRYrpL4R6VZ9gj22UQUsqRI=", + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npm.taobao.org/get-stream/download/get-stream-5.1.0.tgz", + "integrity": "sha1-ASA83JJZf5uQkGfD5lbMH008Tck=", + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/lowercase-keys/download/lowercase-keys-2.0.0.tgz", + "integrity": "sha1-JgPni3tLAAbLyi+8yKMgJVislHk=" + } + } + }, + "chromium-pickle-js": { + "version": "0.2.0", + "resolved": "https://registry.npm.taobao.org/chromium-pickle-js/download/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha1-BKEGZywYsIWrd02YPfo+oTjyIgU=", + "dev": true + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/clone-response/download/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npm.taobao.org/commander/download/commander-2.20.3.tgz?cache=0&sync_timestamp=1587782011624&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcommander%2Fdownload%2Fcommander-2.20.3.tgz", + "integrity": "sha1-/UhehMA+tIgcIHIrpIA16FMa6zM=", + "dev": true + }, + "compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/compare-version/download/compare-version-0.1.2.tgz", + "integrity": "sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npm.taobao.org/concat-stream/download/concat-stream-1.6.2.tgz", + "integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npm.taobao.org/config-chain/download/config-chain-1.1.12.tgz", + "integrity": "sha1-D96NCRIA616AjK8l/mGMAvSOTvo=", + "optional": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "core-js": { + "version": "3.6.5", + "resolved": "https://registry.npm.taobao.org/core-js/download/core-js-3.6.5.tgz", + "integrity": "sha1-c5XcJzrzf7LlDpvT2f6EEoUjHRo=", + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cross-zip": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/cross-zip/download/cross-zip-3.1.0.tgz", + "integrity": "sha1-K30z8qiTv4PiMsy6v0xscG9rMTw=", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/rimraf/download/rimraf-3.0.2.tgz", + "integrity": "sha1-8aVAK6YiCtUswSgrrBrjqkn9Bho=", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "cuint": { + "version": "0.2.2", + "resolved": "https://registry.npm.taobao.org/cuint/download/cuint-0.2.2.tgz", + "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=", + "dev": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npm.taobao.org/decompress-response/download/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/defer-to-connect/download/defer-to-connect-1.1.3.tgz", + "integrity": "sha1-MxrgUMCNz3ifjIOnuB8O2U9KxZE=" + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/define-properties/download/define-properties-1.1.3.tgz", + "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=", + "optional": true, + "requires": { + "object-keys": "^1.0.12" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/object-keys/download/object-keys-1.1.1.tgz", + "integrity": "sha1-HEfyct8nfzsdrwYWd9nILiMixg4=", + "optional": true + } + } + }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/detect-node/download/detect-node-2.0.4.tgz", + "integrity": "sha1-AU7o+PZpxcWAI9pkuBecCDooxGw=", + "optional": true + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npm.taobao.org/duplexer3/download/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "electron": { + "version": "9.0.2", + "resolved": "https://registry.npm.taobao.org/electron/download/electron-9.0.2.tgz", + "integrity": "sha1-NhkkzoMzlvGkWsIZX0QrkutPj10=", + "requires": { + "@electron/get": "^1.0.1", + "@types/node": "^12.0.12", + "extract-zip": "^1.0.3" + }, + "dependencies": { + "@types/node": { + "version": "12.12.44", + "resolved": "https://registry.npm.taobao.org/@types/node/download/@types/node-12.12.44.tgz", + "integrity": "sha1-DUAKFFOtyzWbEzrM6uTdi7DgoVk=" + } + } + }, + "electron-notarize": { + "version": "0.2.1", + "resolved": "https://registry.npm.taobao.org/electron-notarize/download/electron-notarize-0.2.1.tgz", + "integrity": "sha1-dZ6ABt7K4ZE0+CmW7ZENsm2Rksw=", + "dev": true, + "requires": { + "debug": "^4.1.1", + "fs-extra": "^8.1.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz?cache=0&sync_timestamp=1589881689076&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-4.1.1.tgz", + "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npm.taobao.org/fs-extra/download/fs-extra-8.1.0.tgz", + "integrity": "sha1-SdQ8RaiM2Wd2aMt74bRu/bjS4cA=", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } + } + }, + "electron-osx-sign": { + "version": "0.4.16", + "resolved": "https://registry.npm.taobao.org/electron-osx-sign/download/electron-osx-sign-0.4.16.tgz", + "integrity": "sha1-C+jlebLZ+kwS0qIfBjiYKUs0NKo=", + "dev": true, + "requires": { + "bluebird": "^3.5.0", + "compare-version": "^0.1.2", + "debug": "^2.6.8", + "isbinaryfile": "^3.0.2", + "minimist": "^1.2.0", + "plist": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz?cache=0&sync_timestamp=1589881689076&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "electron-packager": { + "version": "14.2.1", + "resolved": "https://registry.npm.taobao.org/electron-packager/download/electron-packager-14.2.1.tgz", + "integrity": "sha1-4YhO7mCEVeceljQnF+BSfSWjKd8=", + "dev": true, + "requires": { + "@electron/get": "^1.6.0", + "asar": "^2.0.1", + "cross-zip": "^3.0.0", + "debug": "^4.0.1", + "electron-notarize": "^0.2.0", + "electron-osx-sign": "^0.4.11", + "fs-extra": "^8.1.0", + "galactus": "^0.2.1", + "get-package-info": "^1.0.0", + "junk": "^3.1.0", + "parse-author": "^2.0.0", + "plist": "^3.0.0", + "rcedit": "^2.0.0", + "resolve": "^1.1.6", + "sanitize-filename": "^1.6.0", + "semver": "^6.0.0", + "yargs-parser": "^16.0.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz?cache=0&sync_timestamp=1589881689076&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-4.1.1.tgz", + "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npm.taobao.org/fs-extra/download/fs-extra-8.1.0.tgz", + "integrity": "sha1-SdQ8RaiM2Wd2aMt74bRu/bjS4cA=", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-6.3.0.tgz", + "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", + "dev": true + } + } + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/encodeurl/download/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "optional": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npm.taobao.org/end-of-stream/download/end-of-stream-1.4.4.tgz?cache=0&sync_timestamp=1569416272686&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fend-of-stream%2Fdownload%2Fend-of-stream-1.4.4.tgz", + "integrity": "sha1-WuZKX0UFe682JuwU2gyl5LJDHrA=", + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/es6-error/download/es6-error-4.1.1.tgz", + "integrity": "sha1-njr0B0Wd7tR+mpH5uIWoTrBcVh0=", + "optional": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-4.0.0.tgz?cache=0&sync_timestamp=1587627395453&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fescape-string-regexp%2Fdownload%2Fescape-string-regexp-4.0.0.tgz", + "integrity": "sha1-FLqDpdNz49MR5a/KKc9b+tllvzQ=", + "optional": true + }, + "extract-zip": { + "version": "1.7.0", + "resolved": "https://registry.npm.taobao.org/extract-zip/download/extract-zip-1.7.0.tgz", + "integrity": "sha1-VWzDrp339FLEk6DPtRzDAneUCSc=", + "requires": { + "concat-stream": "^1.6.2", + "debug": "^2.6.9", + "mkdirp": "^0.5.4", + "yauzl": "^2.10.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz?cache=0&sync_timestamp=1589881689076&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz", + "integrity": "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=" + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.5.tgz", + "integrity": "sha1-2Rzv1i0UNsoPQWIOJRKI1CAJne8=", + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/fd-slicer/download/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "requires": { + "pend": "~1.2.0" + } + }, + "flora-colossus": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/flora-colossus/download/flora-colossus-1.0.1.tgz", + "integrity": "sha1-q6GYQlqBhTQeZPnSpqlv2aPL25M=", + "dev": true, + "requires": { + "debug": "^4.1.1", + "fs-extra": "^7.0.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz?cache=0&sync_timestamp=1589881689076&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-4.1.1.tgz", + "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npm.taobao.org/fs-extra/download/fs-extra-7.0.1.tgz", + "integrity": "sha1-TxicRKoSO4lfcigE9V6iPq3DSOk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } + } + }, + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "galactus": { + "version": "0.2.1", + "resolved": "https://registry.npm.taobao.org/galactus/download/galactus-0.2.1.tgz", + "integrity": "sha1-y+0tIKQMH1Z5o1kI4rlBVzPnjbk=", + "dev": true, + "requires": { + "debug": "^3.1.0", + "flora-colossus": "^1.0.0", + "fs-extra": "^4.0.0" + } + }, + "get-package-info": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/get-package-info/download/get-package-info-1.0.0.tgz", + "integrity": "sha1-ZDJ5ZWPigRPNlHTbvQAFKYWkmZw=", + "dev": true, + "requires": { + "bluebird": "^3.1.1", + "debug": "^2.2.0", + "lodash.get": "^4.0.0", + "read-pkg-up": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz?cache=0&sync_timestamp=1589881689076&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/load-json-file/download/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/path-type/download/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/read-pkg/download/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/read-pkg-up/download/read-pkg-up-2.0.0.tgz?cache=0&sync_timestamp=1575620465504&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fread-pkg-up%2Fdownload%2Fread-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/strip-bom/download/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/get-stream/download/get-stream-4.1.0.tgz", + "integrity": "sha1-wbJVV189wh1Zv8ec09K0axw6VLU=", + "requires": { + "pump": "^3.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npm.taobao.org/glob/download/glob-7.1.6.tgz", + "integrity": "sha1-FB8zuBp8JJLhJVlDB0gMRmeSeKY=", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "global-agent": { + "version": "2.1.12", + "resolved": "https://registry.npm.taobao.org/global-agent/download/global-agent-2.1.12.tgz", + "integrity": "sha1-5K44Ercxqegcv4Jfk3fvRQqOQZU=", + "optional": true, + "requires": { + "boolean": "^3.0.1", + "core-js": "^3.6.5", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "dependencies": { + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-7.3.2.tgz", + "integrity": "sha1-YElisFK4HtB4aq6EOJ/7pw/9OTg=", + "optional": true + } + } + }, + "global-tunnel-ng": { + "version": "2.7.1", + "resolved": "https://registry.npm.taobao.org/global-tunnel-ng/download/global-tunnel-ng-2.7.1.tgz", + "integrity": "sha1-0DtRAt/eOmmRT17n2GdhyjXVfY8=", + "optional": true, + "requires": { + "encodeurl": "^1.0.2", + "lodash": "^4.17.10", + "npm-conf": "^1.1.3", + "tunnel": "^0.0.6" + } + }, + "globalthis": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/globalthis/download/globalthis-1.0.1.tgz", + "integrity": "sha1-QBFvXZwHH56PsAN2VN8as6g7fvk=", + "optional": true, + "requires": { + "define-properties": "^1.1.3" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npm.taobao.org/got/download/got-9.6.0.tgz", + "integrity": "sha1-7fRefWf5lUVwXeH3u+7rEhdl7YU=", + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", + "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==" + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/http-cache-semantics/download/http-cache-semantics-4.1.0.tgz", + "integrity": "sha1-SekcXL82yblLz81xwj1SSex045A=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "optional": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npm.taobao.org/isbinaryfile/download/isbinaryfile-3.0.3.tgz", + "integrity": "sha1-XW3vPt6/boyoyunDAYOoBLX4voA=", + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/json-buffer/download/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "optional": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "junk": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/junk/download/junk-3.1.0.tgz", + "integrity": "sha1-MUmQmNkCt+mMXZucgPQ0V6iKv6E=", + "dev": true + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/keyv/download/keyv-3.1.0.tgz", + "integrity": "sha1-7MIoSG9pmR5J6UdkhaW+Ho/FxNk=", + "requires": { + "json-buffer": "3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npm.taobao.org/lodash/download/lodash-4.17.15.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.15.tgz", + "integrity": "sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg=" + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npm.taobao.org/lodash.get/download/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/lowercase-keys/download/lowercase-keys-1.0.1.tgz", + "integrity": "sha1-b54wtHCE2XGnyCD/FabFFnt0wm8=" + }, + "matcher": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/matcher/download/matcher-3.0.0.tgz", + "integrity": "sha1-vZBg9MW3CqgEHMxvgDaHYJlPMMo=", + "optional": true, + "requires": { + "escape-string-regexp": "^4.0.0" + } + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/mimic-response/download/mimic-response-1.0.1.tgz", + "integrity": "sha1-SSNTiHju9CBjy4o+OweYeBSHqxs=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npm.taobao.org/normalize-url/download/normalize-url-4.5.0.tgz", + "integrity": "sha1-RTNUCH5sqWlXvY9br3U/WYIUISk=" + }, + "npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/npm-conf/download/npm-conf-1.1.3.tgz", + "integrity": "sha1-JWzEe9DiGMJZxOlVC/QTvCGSr/k=", + "optional": true, + "requires": { + "config-chain": "^1.1.11", + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-3.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpify%2Fdownload%2Fpify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "optional": true + } + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/once/download/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/p-cancelable/download/p-cancelable-1.1.0.tgz", + "integrity": "sha1-0HjRWjr0CSIMiG8dmgyi5EGrJsw=" + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-1.3.0.tgz?cache=0&sync_timestamp=1591460481915&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-1.3.0.tgz", + "integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-author": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/parse-author/download/parse-author-2.0.0.tgz", + "integrity": "sha1-00YL8d3Q367tQtp1QkLmX7aEqB8=", + "dev": true, + "requires": { + "author-regex": "^1.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/pend/download/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "plist": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/plist/download/plist-3.0.1.tgz", + "integrity": "sha1-qbkx0XwwTokS7wujvdYYK68uH4w=", + "dev": true, + "requires": { + "base64-js": "^1.2.3", + "xmlbuilder": "^9.0.7", + "xmldom": "0.1.x" + } + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/prepend-http/download/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz", + "integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I=" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/progress/download/progress-2.0.3.tgz", + "integrity": "sha1-foz42PW48jnBvGi+tOt4Vn1XLvg=" + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npm.taobao.org/proto-list/download/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "optional": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/pump/download/pump-3.0.0.tgz", + "integrity": "sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ=", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rcedit": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/rcedit/download/rcedit-2.2.0.tgz", + "integrity": "sha1-O/5xJIdJ+oIf7ybto9NfTg7kevw=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/responselike/download/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npm.taobao.org/rimraf/download/rimraf-2.7.1.tgz", + "integrity": "sha1-NXl/E6f9rcVmFCwp1PB8ytSD4+w=", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "roarr": { + "version": "2.15.3", + "resolved": "https://registry.npm.taobao.org/roarr/download/roarr-2.15.3.tgz", + "integrity": "sha1-ZSSKKRoVrz6/12fL9+RMtALR2DY=", + "optional": true, + "requires": { + "boolean": "^3.0.0", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz?cache=0&sync_timestamp=1589129611964&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.1.2.tgz", + "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" + }, + "sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npm.taobao.org/sanitize-filename/download/sanitize-filename-1.6.3.tgz", + "integrity": "sha1-dV69dSBFkxl34wsgJdNA18kJA3g=", + "requires": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/semver-compare/download/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "optional": true + }, + "serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npm.taobao.org/serialize-error/download/serialize-error-7.0.1.tgz?cache=0&sync_timestamp=1589282114914&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fserialize-error%2Fdownload%2Fserialize-error-7.0.1.tgz", + "integrity": "sha1-8TYLBEf2H/tIPsQVfHN/q313jhg=", + "optional": true, + "requires": { + "type-fest": "^0.13.1" + } + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.1.2.tgz", + "integrity": "sha1-2hdlJiv4wPVxdJ8q1sJjACB65nM=", + "optional": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "tmp": { + "version": "0.1.0", + "resolved": "https://registry.npm.taobao.org/tmp/download/tmp-0.1.0.tgz?cache=0&sync_timestamp=1588178859061&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftmp%2Fdownload%2Ftmp-0.1.0.tgz", + "integrity": "sha1-7kNKTiJUMILilLpiAdzG6v76KHc=", + "dev": true, + "requires": { + "rimraf": "^2.6.3" + } + }, + "tmp-promise": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/tmp-promise/download/tmp-promise-1.1.0.tgz", + "integrity": "sha1-u5JNI5ApFXubwdUGpqo0H4sT5kw=", + "dev": true, + "requires": { + "bluebird": "^3.5.0", + "tmp": "0.1.0" + } + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/to-readable-stream/download/to-readable-stream-1.0.0.tgz", + "integrity": "sha1-zgqgwvPfat+FLvtASng+d8BHV3E=" + }, + "truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/truncate-utf8-bytes/download/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=", + "requires": { + "utf8-byte-length": "^1.0.1" + } + }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npm.taobao.org/tunnel/download/tunnel-0.0.6.tgz", + "integrity": "sha1-cvExSzSlsZLbASMk3yzFh8pH+Sw=", + "optional": true + }, + "type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npm.taobao.org/type-fest/download/type-fest-0.13.1.tgz?cache=0&sync_timestamp=1590463280921&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftype-fest%2Fdownload%2Ftype-fest-0.13.1.tgz", + "integrity": "sha1-AXLLW86AsL1ULqNI21DH4hg02TQ=", + "optional": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npm.taobao.org/typedarray/download/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typescript": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz", + "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/url-parse-lax/download/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "requires": { + "prepend-http": "^2.0.0" + } + }, + "utf8-byte-length": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/utf8-byte-length/download/utf8-byte-length-1.0.4.tgz", + "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npm.taobao.org/xmlbuilder/download/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "dev": true + }, + "xmldom": { + "version": "0.1.31", + "resolved": "https://registry.npm.taobao.org/xmldom/download/xmldom-0.1.31.tgz", + "integrity": "sha1-t2yaG9nwqXN+WnLcNyMc84N14v8=", + "dev": true + }, + "yargs-parser": { + "version": "16.1.0", + "resolved": "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-16.1.0.tgz", + "integrity": "sha1-c3R9U64YfnuNvjM/lXFMduoA7PE=", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npm.taobao.org/camelcase/download/camelcase-5.3.1.tgz?cache=0&sync_timestamp=1586229901005&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcamelcase%2Fdownload%2Fcamelcase-5.3.1.tgz", + "integrity": "sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA=", + "dev": true + } + } + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npm.taobao.org/yauzl/download/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..c58c759 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "google-translate-electron", + "author": "mattuy", + "version": "0.1.0", + "main": "./src/index.js", + "description": "Google Translate for Windows Desktop, built with Electron", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "electron .", + "package": "electron-packager ./ --overwrite --win --out ./bin --icon ./appicon.ico --app-copyright \"copyright@mattuy\" --win32metadata.CompanyName=\"\"" + }, + "productName": "Google Translate Desktop", + "originalFilename": "Google Translate Desktop", + "dependencies": { + "lodash": "^4.17.15" + }, + "devDependencies": { + "@types/lodash": "^4.14.155", + "electron": "^5.0.6", + "electron-packager": "^14.2.1", + "typescript": "^3.5.3" + } +} diff --git a/src/assets/icon.ico b/src/assets/icon.ico new file mode 100644 index 0000000..eafa8f0 Binary files /dev/null and b/src/assets/icon.ico differ diff --git a/src/config.js b/src/config.js new file mode 100644 index 0000000..46a8f6c --- /dev/null +++ b/src/config.js @@ -0,0 +1,40 @@ +const fs = require('fs'); +const { promisify } = require('util'); +const toast = require('./notify'); +const { debounce } = require('lodash'); + +const config = { + mainWindowWidth: 1024, + mainWindowHeight: 586, + url: 'https://translate.google.cn/', + autoStart: false, + miniWindowEnabled: true, + miniShortcut: 'CmdOrCtrl+Alt+M', + extraCssForMain: '', + extraCssForMini: '', + minimizeToTrayWhenClose: true, + minimizeToTrayWenStart: true, +}; + +try { + let userConfig = fs.readFileSync('./config.json'); + if (userConfig) { + Object.assign(config, JSON.parse(userConfig.toString())); + } +} +catch { } + +async function flushConfig() { + const flush = promisify(fs.writeFile.bind(fs)); + try { + await flush('./config.json', JSON.stringify(config, null, 4)); + } + catch { + toast.show("保存配置失败。", { messageType: 'error' }); + } +} + +module.exports = { + config, + flushConfig: debounce(flushConfig, 1000, { trailing: true }) +}; diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..86b7749 --- /dev/null +++ b/src/index.js @@ -0,0 +1,166 @@ +const path = require('path'); +const { app, globalShortcut, BrowserWindow, Menu, Tray } = require('electron'); +const createMiniWindow = require('./mini'); +const createMainWindow = require('./main'); +const getMenu = require('./menu'); +const { config, flushConfig } = require('./config'); +const toast = require('./notify'); + +//将tray保存到全局变量,防止其被自动回收 +let tray; + +/** @type BrowserWindow */ +let mainWindow; +/** @type BrowserWindow */ +let miniWindow; + +app.on('ready', () => { + setupTray(); + toggleAutoStart(true); + + mainWindow = createMainWindow(); + mainWindow.on('close', ev => { + if (config.minimizeToTrayWhenClose) { + ev.preventDefault(); + mainWindow.hide(); + } + }); + mainWindow.on('closed', () => { + if (miniWindow) { + toast.dismiss(); + globalShortcut.unregisterAll(); + miniWindow.destroy(); + } + }); + //主窗口隐藏时设置mini窗口的父窗口为主窗口,防止主窗口意外关闭但mini窗口还保留着导致程序残留在内存中 + mainWindow.on('hide', () => { + if (miniWindow) { + miniWindow.setParentWindow(mainWindow); + } + }); + //主窗口显示时如果mini窗口的父窗口是主窗口,mini窗口获得焦点时父窗口也会弹出来。。emm又没找到其他靠谱的方法 + mainWindow.on('show', () => { + if (miniWindow) { + miniWindow.setParentWindow(null); + } + }); + if (!config.minimizeToTrayWenStart) { + mainWindow.show(); + } + else { + toast.show("Google Translate Desktop已在后台运行。", null, { + use: 'notification', + clickCallback: () => mainWindow.show() + }); + } + registerMiniWindow(); + const mainMenu = getMenu(mainWindow, miniWindow, mainWindow); + mainWindow.setMenu(mainMenu); +}); + +function registerMiniWindow() { + // if (!config.miniWindowEnabled) { + // return; + // } + miniWindow = createMiniWindow(); + miniWindow.setParentWindow(mainWindow); + const miniMenu = getMenu(mainWindow, miniWindow, miniWindow); + miniWindow.setMenu(miniMenu); + if (config.miniWindowEnabled) { + toggleMiniShortcut(true); + } +} + +function setupTray() { + tray = new Tray(path.resolve(__dirname, 'assets/icon.ico')); + const contextMenu = Menu.buildFromTemplate([ + { label: "显示主界面", click: () => toggleMainWindowVisibility() }, + { label: "显示Mini窗口", click: () => toggleMiniWindowVisibility() }, + { + type: 'checkbox', + label: "开机启动", + checked: config.autoStart, + click: menu => menu.checked = toggleAutoStart() + }, + { + type: 'checkbox', + label: "启用MINI窗口快捷键", + checked: config.miniWindowEnabled, + click: menu => menu.checked = toggleMiniShortcut() + }, + { label: "退出", click: () => app.exit() } + ]); + tray.setToolTip("Google Translate Desktop"); + tray.on('click', () => toggleMainWindowVisibility()); + tray.setContextMenu(contextMenu); +} + +function toggleAutoStart(initial) { + if (!initial) { + config.autoStart = !config.autoStart; + } + app.setLoginItemSettings({ + openAtLogin: config.autoStart, + path: process.execPath, + openAsHidden: false, + args: [ + '--autoStart' + ] + }); + if (config.autoStart) { + toast.show("已允许Google Translate Desktop在您登录时自动启动。", "提示"); + } + else { + toast.show("已禁止Google Translate Desktop在您登录时自动启动。", "提示"); + } + if (!initial) { + flushConfig(); + } + return config.autoStart; +} + +//启用/禁用mini窗口快捷键 +function toggleMiniShortcut(initial) { + let enabled = initial ? config.miniWindowEnabled : !config.miniWindowEnabled; + let success = true; + if (enabled) { + if (!globalShortcut.register(config.miniShortcut, () => toggleMiniWindowVisibility())) { + toast.show("快捷键注册失败,请检查设置的快捷键是否被其他软件占用。", "错误", { + type: 'error' + }); + success = false; + } + } + else { + globalShortcut.unregister(config.miniShortcut); + } + if (success) { + config.miniWindowEnabled = enabled; + if (!initial) { + flushConfig(); + } + } + return enabled; +} + +function toggleMiniWindowVisibility() { + if (!miniWindow) { return; } + if (miniWindow.isVisible()) { + miniWindow.hide(); + } + else { + miniWindow.show(); + miniWindow.focus(); + } +} + +function toggleMainWindowVisibility() { + if (!mainWindow) { return; } + if (mainWindow.isVisible()) { + mainWindow.hide(); + } + else { + mainWindow.show(); + mainWindow.focus(); + } +} diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..8c0baf0 --- /dev/null +++ b/src/main.js @@ -0,0 +1,39 @@ +const path = require('path'); +const { BrowserWindow } = require('electron'); +const getMenu = require('./menu'); +const { config } = require('./config'); + +function createMainWindow() { + const win = new BrowserWindow({ + width: config.mainWindowWidth, + height: config.mainWindowHeight, + icon: path.resolve(__dirname, './assets/icon.ico'), + title: 'Google Translate', + show: false, + webPreferences: { + nodeIntegration: false + }, + useContentSize: true, + autoHideMenuBar: true, + }); + + win.loadURL(config.url); + win.webContents.on('dom-ready', () => { + win.webContents.insertCSS(` + /* 隐藏通知 */ + .notification-area { + display: none !important; + } + /* 防止高度较小时出现双滚动条 */ + .frame { + overflow: visible !important; + } + `); + if (config.extraCssForMain) { + win.webContents.insertCSS(config.extraCssForMain); + } + }); + return win; +} + +module.exports = createMainWindow; \ No newline at end of file diff --git a/src/menu.js b/src/menu.js new file mode 100644 index 0000000..c57b90a --- /dev/null +++ b/src/menu.js @@ -0,0 +1,36 @@ +const { Menu } = require('electron'); + +function getMenu(/** @type Electron.BrowserWindow */mainWindow, miniWindow, current) { + const template = [{ + label: "选项", + submenu: Menu.buildFromTemplate([ + { + label: "显示主界面", + click: () => { + if (!mainWindow) { return; } + mainWindow.show(); + mainWindow.focus(); + } + }, + { + label: "显示MINI窗口", + click: () => { + if (!miniWindow) { return; } + miniWindow.show(); + miniWindow.focus(); + } + }, + { + label: "打开调试控制台", + click: () => current.webContents.openDevTools() + }, + { + label: "退出", + role: 'quit' + } + ]) + }]; + return Menu.buildFromTemplate(template); +} + +module.exports = getMenu; \ No newline at end of file diff --git a/src/mini.js b/src/mini.js new file mode 100644 index 0000000..dc42d9f --- /dev/null +++ b/src/mini.js @@ -0,0 +1,110 @@ +const path = require('path'); +const { BrowserWindow } = require('electron'); +const getMenu = require('./menu'); +const { config } = require('./config'); + +function createMiniWindow () { + let miniWindow = new BrowserWindow({ + width: 500, + height: 315, + minWidth: 500, + minHeight: 315, + maxWidth: 500, + maxHeight: 315, + icon: path.resolve(__dirname, './assets/icon.ico'), + webPreferences: { + nodeIntegration: false + }, + title: "Google Translate Mini", + autoHideMenuBar: true, + show: false, + minimizable: false, + maximizable: true, + alwaysOnTop: true, + fullscreenable: false, + skipTaskbar: true, + }); + + miniWindow.on('focus', () => { + miniWindow.setOpacity(1); + }); + miniWindow.on('blur', () => { + miniWindow.setOpacity(0.618); + }); + miniWindow.on('close', ev => { + ev.preventDefault(); + miniWindow.hide(); + }); + + miniWindow.loadURL(config.url); + miniWindow.webContents.on('dom-ready', () => { + miniWindow.webContents.executeJavaScript(` + setTimeout(() => { + console.log('throw'); + throw('crashed'); + }, 10000); + var source = document.getElementById('source'); + if (source) { + document.addEventListener('visibilitychange', () => { + if (document.visibilityState === 'hidden') { + source.value = ''; + } + else { + source.focus(); + } + }); + } + `); + miniWindow.webContents.insertCSS(` + /* 隐藏通知,文本/文件切换栏 */ + .container .input-button-container, + .notification-area { + display: none !important; + } + /* mini窗口隐藏header和历史记录按钮和拼音 */ + .tlid-source-transliteration-container.source-transliteration-container, + header.gb_sa.gb_2a.gb_5e.gb_ta, .gp-footer { + display: none !important; + } + /* 防止高度较小时出现双滚动条 */ + .frame { + overflow: visible !important; + } + /* 去除语言选择栏顶部边框 */ + .tlid-language-bar.ls-wrap { + border-top: none; + } + /* 减小输入内容高度 */ + .tlid-copy-target { + margin-bottom: 0; + } + /* 减小结果内容高度 */ + .result.tlid-copy-target { + height: 72px; + min-height: 72px; + } + /* 缩小语言选择栏高度 */ + a.ls-select.new-ls-select { + line-height: 32px; + } + .tlid-language-bar.ls-wrap { + height: 40px; + overflow: hidden; + } + .swap-wrap { + transform: translateY(-8px); + } + /* 取消结果栏聚焦时的外边框(一般来说不应该这样做) */ + .result-shield-container.tlid-copy-target { + outline: none; + } + `); + if (config.extraCssForMini) { + miniWindow.insertCSS(config.extraCssForMini); + } + }); + + return miniWindow; +} + +module.exports = createMiniWindow; diff --git a/src/notify.js b/src/notify.js new file mode 100644 index 0000000..7f0d5d8 --- /dev/null +++ b/src/notify.js @@ -0,0 +1,38 @@ +const path = require('path'); +const { Notification, dialog } = require('electron'); + +let current = null; + +function notify(message, title, ops) { + const use = ops ? ops.use : 'auto'; + if (use === 'dialog' || (!Notification.isSupported() && use !== 'notification')) { + let options = { message, title: title || "信息" }; + if (ops && ops.messageType) { + options.type = ops.messageType; + } + dialog.showMessageBox(null, options); + return; + } + if (current) { + current.close(); + } + current = new Notification({ + title: "Google Translate Desktop", + body: message, + subtitle: ops && ops.subtitle, + icon: path.resolve(__dirname, './assets/icon.ico') + }); + current.show(); + if (ops && ops.clickCallback) { + current.on('click', ops.clickCallback); + } +} + +function dismiss() { + current && current.close(); +} + +module.exports = { + show: notify, + dismiss +};