first version commit
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@@ -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 })
|
||||
};
|
||||
+166
@@ -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();
|
||||
}
|
||||
}
|
||||
+39
@@ -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;
|
||||
+36
@@ -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;
|
||||
+110
@@ -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;
|
||||
@@ -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
|
||||
};
|
||||
Reference in New Issue
Block a user