From dc054e40db927ec941299552ee4a70296bab21c7 Mon Sep 17 00:00:00 2001 From: mattuy Date: Sat, 13 Jun 2020 14:11:06 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=94=B9=E8=BF=9B=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E4=BD=93=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 定期执行自动操作保持mini窗口活跃防止长时间无操作后唤醒卡顿; 主窗口隐藏时允许mini窗口出现在Windows切换视图中(取消skipTaskBar标识)以快速切换; --- README.md | 13 +++++-- src/config.js | 1 + src/index.js | 41 +++++----------------- src/main.js | 18 ++++++++-- src/mini.js | 95 ++++++++++++++++++++++++++++++++++++++------------- 5 files changed, 107 insertions(+), 61 deletions(-) diff --git a/README.md b/README.md index 9b99f95..00b54c9 100644 --- a/README.md +++ b/README.md @@ -25,15 +25,18 @@ Google Translate网页版的封装,通过[Electron](https://www.electronjs.org * 允许配置默认主窗口尺寸; * Mini窗口自动获取输入焦点; * 支持开机启动; +* 允许Mini窗口隐藏时保持活跃以快速响应;
* 不支持离线使用; * 不支持取词划词; * 未测试Windows之外的平台; -对于Mini窗口自动获取输入焦点,由于是通过`dom-ready`事件注入JavaScript实现,因此在`dom-ready`之前Mini窗口无法自动获取焦点。而这需要大概十几秒,因为`translate.google.cn`尝试从`google.com`获取一些资源,而访问google.com会等待超时后失败(国内环境),但这些资源并不是完成翻译功能所必须的,因此并不影响翻译功能的使用。但未完成的非ajax请求会让`dom-ready`事件迟迟不能触发,导致依赖此事件注入JavaScript的代码直到请求超时后才执行。 +对于Mini窗口自动获取输入焦点和自动清除输入,由于是通过`dom-ready`事件注入JavaScript实现,因此在`dom-ready`之后才能生效。而这需要大概十几秒,因为`translate.google.cn`尝试从`google.com`获取一些资源,而访问google.com会等待超时后失败(国内环境),但这些资源并不是完成翻译功能所必须的,因此并不影响翻译功能的使用。但未完成的非ajax请求会让`dom-ready`事件迟迟不能触发,导致依赖此事件注入JavaScript的代码直到请求超时后才执行。 但这只在程序启动时发生,个人认为勉强能够忍受,就没有再折腾。如果有必要,或许可以通过`ServiceWorker`拦截? +另外,在此期间,对于0.2版本可能会出现输入内容离奇消失的情况(每次运行周期最多出现一次)。这是因为程序在Mini窗口隐藏时自动清除输入,但由于注入的JS代码需要`dom-ready`事件后才执行,所以清除输入的代码可能会在不合适的时机被执行。但至多只可能发生一次。 + 对于封装的url,本程序仅对translate.google.cn做了样式微调,如果换成其它的url,可能需要自行调整样式。配置项中允许更改url参数来加载其他网页。如果需要,还可以通过提供额外CSS来调整样式,它们将被注入页面,见[配置项](##配置项)。 注意,你可能需要为你的样式加上!important标记以覆盖更高优先级的原始样式,因为CSS以嵌入式CSS的方式插入。 @@ -72,14 +75,18 @@ Mini窗口的大小是固定的,想要修改只能修改代码。为了在更 | extraCssForMini | string | "" | 额外插入Mini窗口的的CSS | minimizeToTrayWhenClose | boolean | true | 关闭主窗口时最小化到托盘 | minimizeToTrayWenStart | boolean | true | 启动时自动隐藏主窗口 +| keepActiveInterval | number | 60000 | 自动操作Mini窗口以使其保持活跃的周期,单位ms,最低1000,为0禁止 ## 使用截图 -主窗口 +主窗口 +主窗口 主窗口-有内容 -迷你窗口-有内容 +Mini窗口 + +迷你窗口-有内容 迷你窗口-有内容 diff --git a/src/config.js b/src/config.js index 46a8f6c..8661222 100644 --- a/src/config.js +++ b/src/config.js @@ -14,6 +14,7 @@ const config = { extraCssForMini: '', minimizeToTrayWhenClose: true, minimizeToTrayWenStart: true, + keepActiveInterval: 60000 }; try { diff --git a/src/index.js b/src/index.js index 86b7749..05b68fc 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,7 @@ const path = require('path'); const { app, globalShortcut, BrowserWindow, Menu, Tray } = require('electron'); -const createMiniWindow = require('./mini'); -const createMainWindow = require('./main'); +const { createMiniWindow, toggleMiniWindowVisibility } = require('./mini'); +const { createMainWindow, toggleMainWindowVisibility } = require('./main'); const getMenu = require('./menu'); const { config, flushConfig } = require('./config'); const toast = require('./notify'); @@ -36,12 +36,14 @@ app.on('ready', () => { mainWindow.on('hide', () => { if (miniWindow) { miniWindow.setParentWindow(mainWindow); + miniWindow.setSkipTaskbar(false); } }); //主窗口显示时如果mini窗口的父窗口是主窗口,mini窗口获得焦点时父窗口也会弹出来。。emm又没找到其他靠谱的方法 mainWindow.on('show', () => { if (miniWindow) { miniWindow.setParentWindow(null); + miniWindow.setSkipTaskbar(true); } }); if (!config.minimizeToTrayWenStart) { @@ -59,10 +61,7 @@ app.on('ready', () => { }); function registerMiniWindow() { - // if (!config.miniWindowEnabled) { - // return; - // } - miniWindow = createMiniWindow(); + miniWindow = createMiniWindow(); miniWindow.setParentWindow(mainWindow); const miniMenu = getMenu(mainWindow, miniWindow, miniWindow); miniWindow.setMenu(miniMenu); @@ -74,8 +73,8 @@ function registerMiniWindow() { function setupTray() { tray = new Tray(path.resolve(__dirname, 'assets/icon.ico')); const contextMenu = Menu.buildFromTemplate([ - { label: "显示主界面", click: () => toggleMainWindowVisibility() }, - { label: "显示Mini窗口", click: () => toggleMiniWindowVisibility() }, + { label: "显示主界面", click: () => toggleMainWindowVisibility(mainWindow) }, + { label: "显示Mini窗口", click: () => toggleMiniWindowVisibility(miniWindow) }, { type: 'checkbox', label: "开机启动", @@ -91,7 +90,7 @@ function setupTray() { { label: "退出", click: () => app.exit() } ]); tray.setToolTip("Google Translate Desktop"); - tray.on('click', () => toggleMainWindowVisibility()); + tray.on('click', () => toggleMainWindowVisibility(mainWindow)); tray.setContextMenu(contextMenu); } @@ -124,7 +123,7 @@ function toggleMiniShortcut(initial) { let enabled = initial ? config.miniWindowEnabled : !config.miniWindowEnabled; let success = true; if (enabled) { - if (!globalShortcut.register(config.miniShortcut, () => toggleMiniWindowVisibility())) { + if (!globalShortcut.register(config.miniShortcut, () => toggleMiniWindowVisibility(miniWindow))) { toast.show("快捷键注册失败,请检查设置的快捷键是否被其他软件占用。", "错误", { type: 'error' }); @@ -142,25 +141,3 @@ function toggleMiniShortcut(initial) { } 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 index 8c0baf0..1ee6ef6 100644 --- a/src/main.js +++ b/src/main.js @@ -1,6 +1,5 @@ const path = require('path'); const { BrowserWindow } = require('electron'); -const getMenu = require('./menu'); const { config } = require('./config'); function createMainWindow() { @@ -36,4 +35,19 @@ function createMainWindow() { return win; } -module.exports = createMainWindow; \ No newline at end of file +function toggleMainWindowVisibility(window) { + if (!window) { return; } + if (window.isVisible()) { + window.hide(); + } + else { + window.show(); + window.focus(); + } +} + + +module.exports = { + createMainWindow, + toggleMainWindowVisibility +} \ No newline at end of file diff --git a/src/mini.js b/src/mini.js index dc42d9f..2df06a0 100644 --- a/src/mini.js +++ b/src/mini.js @@ -1,8 +1,14 @@ const path = require('path'); const { BrowserWindow } = require('electron'); -const getMenu = require('./menu'); const { config } = require('./config'); +const miniControl = { + /** 迷你窗口是否处于可视区域 */ + isMiniWindowVisible: true, + previousPos: null +} + + function createMiniWindow () { let miniWindow = new BrowserWindow({ width: 500, @@ -22,7 +28,8 @@ function createMiniWindow () { maximizable: true, alwaysOnTop: true, fullscreenable: false, - skipTaskbar: true, + skipTaskbar: false, + }); miniWindow.on('focus', () => { @@ -33,28 +40,11 @@ function createMiniWindow () { }); miniWindow.on('close', ev => { ev.preventDefault(); - miniWindow.hide(); + toggleMiniWindowVisibility(miniWindow); }); 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, @@ -62,8 +52,9 @@ function createMiniWindow () { display: none !important; } /* mini窗口隐藏header和历史记录按钮和拼音 */ - .tlid-source-transliteration-container.source-transliteration-container, - header.gb_sa.gb_2a.gb_5e.gb_ta, .gp-footer { + header, + .gp-footer, + .tlid-source-transliteration-container.source-transliteration-container { display: none !important; } /* 防止高度较小时出现双滚动条 */ @@ -103,8 +94,64 @@ function createMiniWindow () { miniWindow.insertCSS(config.extraCssForMini); } }); - + miniControl.previousPos = miniWindow.getPosition(); + toggleMiniWindowVisibility(miniWindow); + miniWindow.show(); + let interval = config.keepActiveInterval | 0; + if (miniWindow && interval !== 0) { + interval = Math.max(1000, interval); + setInterval(() => { + if (!miniControl.isMiniWindowVisible) { + miniWindow.webContents.executeJavaScript(` + var source = document.getElementById('source'); + if (source) { + source.value = source.value; + } + `); + } + }, interval); + } return miniWindow; } -module.exports = createMiniWindow; +function toggleMiniWindowVisibility(window) { + if (!window) { return; } + miniControl.isMiniWindowVisible = !miniControl.isMiniWindowVisible; + if (miniControl.isMiniWindowVisible) { + if (miniControl.previousPos) { + window.setPosition(...miniControl.previousPos); + } + else { + window.show(); + } + focusInput(window); + window.focus(); + } + else { + miniControl.previousPos = window.getPosition(); + window.setPosition(-1000, -1000, false); + clearInput(window); + } +} + +function clearInput(window) { + window.webContents.executeJavaScript(` + var source = document.getElementById('source'); + if (source) { + source.value = ''; + } + `); +} +function focusInput (window) { + window.webContents.executeJavaScript(` + var source = document.getElementById('source'); + if (source) { + source.focus(); + } + `); +} + +module.exports = { + createMiniWindow, + toggleMiniWindowVisibility +}