DawnLauncher/src/main/main.js

817 lines
24 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import appInit from "./appInit";
import { app, BrowserWindow, dialog, ipcMain, Menu, protocol, Tray, screen } from "electron";
import { createProtocol } from "vue-cli-plugin-electron-builder/lib";
import classificationIpcEvent from "./classification/ipcEvent";
import itemIpcEvent from "./item/ipcEvent";
import settingIpcEvent from "./setting/ipcEvent";
import ipcEvent from "./ipcEvent";
import settingIndex from "./setting/index";
import path from "path";
import util from "./util";
import itemIndex from "./item/index";
import cacheData from "./cache/data";
import data from "./data";
// 解决透明窗口闪烁
app.commandLine.appendSwitch("wm-window-animations-disabled");
// 数据
const settingData = require("./setting/data");
protocol.registerSchemesAsPrivileged([{ scheme: "app", privileges: { secure: true, standard: true } }]);
// 主窗口
let mainWindow = null;
// 设置窗口
let settingWindow = null;
// 搜索框
let searchWindow = null;
/**
* 创建主窗口
* @param init
* @returns {Promise<void>}
*/
async function createWindow(init) {
// 浏览器开发者工具
let devTools;
// 环境判断
if (process.env.NODE_ENV !== "production") {
// 开发
devTools = true;
} else {
// 正式
devTools = false;
}
if (init) {
// 初始化监听
await ipcEvent();
await classificationIpcEvent();
await itemIpcEvent();
await settingIpcEvent();
// 初始化数据
await settingData.initData();
await data.initData();
await data.splitData();
await data.validData();
// watch
global.mapDirectoryWatcher = new Map();
}
// 记录是否透明
if (global.setting.appearance.backgroundTransparency == 1) {
global.backgroundTransparency = false;
} else {
global.backgroundTransparency = true;
}
// 主窗口
global.mainWindow = mainWindow = new BrowserWindow({
minWidth: 300,
minHeight: 400,
width: 800,
height: 600,
frame: false,
show: false,
maximizable: false,
minimizable: false,
fullscreenable: false,
transparent: global.backgroundTransparency,
skipTaskbar: true,
webPreferences: {
backgroundThrottling: false,
nodeIntegration: true,
contextIsolation: false,
spellcheck: false,
devTools: devTools,
},
});
// 加载页面
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
mainWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
} else {
createProtocol("app");
// Load the index.html when not in development
mainWindow.loadURL("app://./index.html");
}
// 加载完webContents后再显示窗口
mainWindow.webContents.on("did-finish-load", function () {
// 透明度
mainWindow.setOpacity(Number(global.setting.appearance.transparency));
// 永远居中不可移动
if (global.setting.general.alwaysCenter) {
// 是否可移动
mainWindow.setMovable(false);
} else {
// 是否可移动
mainWindow.setMovable(!global.setting.general.fixedPosition);
}
// 恢复上一次的位置
let bounds = cacheData.cacheStore.get("bounds");
if (bounds != null) {
mainWindow.setBounds(bounds);
}
// 永远置顶
if (global.setting.general.alwaysTop) {
mainWindow.setAlwaysOnTop(true, "screen-saver");
}
// 是否托盘化启动
if (!global.setting.general.startupTray) {
mainWindow.show();
}
// 锁定尺寸
mainWindow.setResizable(!global.setting.general.lockSize);
// 检查更新
let checkUpdate = cacheData.cacheStore.get("checkUpdate");
if (checkUpdate == null || checkUpdate) {
util.checkUpdate("init");
}
// 永远居中
if (global.setting.general.alwaysCenter) {
mainWindow.center();
}
// 判断窗口位置
let displays = util.getWindowInScreen();
if (displays.length == 0) {
// 代表窗口的位置不再任一屏幕内,将窗口位置移动到主窗口
mainWindow.center();
}
// 边缘吸附
util.edgeAdsorb();
});
// 禁用标题栏右键
mainWindow.hookWindowMessage(278, function (e) {
// 窗口禁用
mainWindow.setEnabled(false);
// 延时太快会立刻启动,太慢会妨碍窗口其他操作,可自行测试最佳时间
setTimeout(() => {
mainWindow.setEnabled(true);
}, 100);
return true;
});
// 窗口移动完毕
mainWindow.on("moved", () => {
// 永远居中
if (global.setting.general.alwaysCenter) {
mainWindow.center();
}
// 记录位置
cacheData.cacheStore.set("bounds", mainWindow.getBounds());
// 边缘吸附
util.edgeAdsorb();
});
// 改变窗口大小完毕
mainWindow.on("resized", () => {
// 永远居中
if (global.setting.general.alwaysCenter) {
mainWindow.center();
}
// 记录位置
cacheData.cacheStore.set("bounds", mainWindow.getBounds());
});
// 监听鼠标移动
const mouseEvent = require("./mouse");
mouseEvent.on("mousemove", (data) => {
if (global.setting.general.edgeAutoHide && (global.blurHide == null || !global.blurHide) && !global.setting.general.alwaysCenter) {
autoHide(data, 40, true);
}
});
// 监听鼠标抬起
mouseEvent.on("mouseup", (data) => {
// 中键单击
if (data.button == 3 && global.setting.general.showHideMouseWheelClick) {
if (util.notDisturb()) {
return;
}
if (global.mainWindow.isVisible()) {
// global.mainWindow.hide();
global.mainWindow.webContents.send("hideMainWindowBefore");
} else {
util.showFollowMousePosition();
global.mainWindow.show();
global.mainWindow.focus();
global.blurHide = true;
}
}
// 双击任务栏显示/隐藏窗口
if (global.setting.general.doubleClickTaskbar) {
// 不是左键的话
if (data.button != 1) {
// 清除timeout
clearTimeout(global.doubleClickTimer);
// 清空
global.doubleClickCounter = 0;
return;
}
// 双击操作
let displays = util.getWindowInScreen();
if (displays.length > 1 || displays.length == 0) {
// 清除timeout
clearTimeout(global.doubleClickTimer);
// 清空
global.doubleClickCounter = 0;
return;
}
// 获取鼠标位置
let point = screen.getCursorScreenPoint();
// 判断鼠标是否在当前屏幕内
if (
point.x >= displays[0].bounds.x &&
point.x <= displays[0].bounds.x + displays[0].bounds.width &&
point.y >= displays[0].bounds.y &&
point.y <= displays[0].bounds.y + displays[0].bounds.height
) {
// 判断是否双击在任务栏上
let flag = false;
// 判断任务栏在哪一侧
if (displays[0].bounds.height > displays[0].workArea.height) {
if (displays[0].bounds.y == displays[0].workArea.y) {
// 底部
let top = displays[0].workArea.y + displays[0].workArea.height;
let bottom = displays[0].bounds.y + displays[0].bounds.height;
if (point.y >= top && point.y <= bottom) {
flag = true;
}
} else {
// 顶部
if (point.y >= displays[0].bounds.y && point.y <= displays[0].workArea.y) {
flag = true;
}
}
} else if (displays[0].bounds.width > displays[0].workArea.width) {
if (displays[0].bounds.x == displays[0].workArea.x) {
// 右侧
let left = displays[0].workArea.x + displays[0].workArea.width;
let right = displays[0].bounds.x + displays[0].bounds.width;
if (point.x >= left && point.x <= right) {
flag = true;
}
} else {
// 左侧
if (point.x >= displays[0].bounds.x && point.x <= displays[0].workArea.x) {
flag = true;
}
}
}
if (flag) {
// 监听双击
if (global.doubleClickCounter == null) {
global.doubleClickCounter = 0;
}
// +1
global.doubleClickCounter++;
// 等于2就是双击
if (global.doubleClickCounter != null && global.doubleClickCounter == 2) {
// 清除timeout
clearTimeout(global.doubleClickTimer);
// 清空
global.doubleClickCounter = 0;
let className = global.api.getCursorPosWindowClassName();
if (className.indexOf("MSTask") >= 0 || className == "Shell_TrayWnd") {
if (mainWindow.isVisible()) {
// mainWindow.hide();
global.mainWindow.webContents.send("hideMainWindowBefore");
} else {
util.showFollowMousePosition();
mainWindow.show();
}
}
} else {
// 间隔为500毫秒如果超过500毫秒就代表不是双击
global.doubleClickTimer = setTimeout(function () {
global.doubleClickCounter = 0;
}, 500);
}
} else {
// 清除timeout
clearTimeout(global.doubleClickTimer);
// 清空
global.doubleClickCounter = 0;
}
} else {
// 清除timeout
clearTimeout(global.doubleClickTimer);
// 清空
global.doubleClickCounter = 0;
}
}
});
// 失去焦点
mainWindow.on("blur", () => {
if (global.setting.general.edgeAutoHide && global.blurHide) {
let scaleFactor = screen.getPrimaryDisplay().scaleFactor;
let data = {
x: screen.getCursorScreenPoint().x * scaleFactor,
y: screen.getCursorScreenPoint().y * scaleFactor,
};
autoHide(data, 0, false);
}
if (mainWindow.isVisible()) {
if (global.setting.general.hideLosingFocus && !global.setting.general.alwaysTop) {
// 隐藏
// mainWindow.hide();
global.mainWindow.webContents.send("hideMainWindowBefore");
}
}
});
// 显示窗口
mainWindow.on("show", () => {
// 检测无效项目
if (global.setting.item.checkInvalidItem) {
global.mainWindow.webContents.send("checkInvalidItemResult", JSON.stringify(itemIndex.checkInvalidItem()));
}
// 边缘吸附
util.edgeAdsorb();
// 显示窗口时将输入法切换为英文模式
if (global.setting.general.switchEnglish) {
global.api.SwitchEnglish(mainWindow.getNativeWindowHandle());
}
});
// 隐藏窗口
mainWindow.on("hide", () => {
global.blurHide = null;
});
// 关闭窗口事件
mainWindow.on("close", () => {
// 关闭搜索框
if (searchWindow != null && !searchWindow.isDestroyed()) {
searchWindow.close();
}
// 释放鼠标监听
global.api.disableMouseMove();
});
}
/**
* 创建搜索窗口
* @returns {Promise<void>}
*/
async function createSettingWindow() {
// 浏览器开发者工具
let devTools;
// 环境判断
if (process.env.NODE_ENV !== "production") {
// 开发
devTools = true;
} else {
// 正式
devTools = false;
}
// 设置窗口
global.settingWindow = settingWindow = new BrowserWindow({
width: 600,
height: 500,
frame: false,
show: false,
maximizable: false,
minimizable: false,
fullscreenable: false,
skipTaskbar: true,
parent: mainWindow,
resizable: false,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
spellcheck: false,
devTools: devTools,
},
});
// 加载页面
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
settingWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL + "#/setting");
} else {
createProtocol("app");
// Load the index.html when not in development
settingWindow.loadURL("app://./index.html#setting");
}
// 加载完webContents后再显示窗口
settingWindow.webContents.on("did-finish-load", function () {
// 显示窗口
settingWindow.show();
});
// 禁用标题栏右键
settingWindow.hookWindowMessage(278, function (e) {
// 窗口禁用
settingWindow.setEnabled(false);
// 延时太快会立刻启动,太慢会妨碍窗口其他操作,可自行测试最佳时间
setTimeout(() => {
settingWindow.setEnabled(true);
}, 100);
return true;
});
}
/**
* 创建搜索窗口
* @returns {Promise<void>}
*/
async function createSearchWindow() {
// 是否可以显示
global.searchWindowShow = false;
if (searchWindow != null && !searchWindow.isDestroyed()) {
searchWindow.destroy();
}
// 浏览器开发者工具
let devTools;
// 环境判断
if (process.env.NODE_ENV !== "production") {
// 开发
devTools = true;
} else {
// 正式
devTools = false;
}
// 窗口
global.searchWindow = searchWindow = new BrowserWindow({
width: 600,
height: 44,
type: "toolbar",
frame: false,
show: false,
maximizable: false,
minimizable: false,
fullscreenable: false,
resizable: false,
alwaysOnTop: true,
backgroundColor: global.setting.appearance.theme.mainBackground.replace("bg-[", "").replace("]", ""),
webPreferences: {
backgroundThrottling: false,
nodeIntegration: true,
contextIsolation: false,
spellcheck: false,
devTools: devTools,
},
});
// 加载页面
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
searchWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL + "#/searchWindow");
} else {
createProtocol("app");
// Load the index.html when not in development
searchWindow.loadURL("app://./index.html#searchWindow");
}
// 加载完webContents后再显示窗口
searchWindow.webContents.on("did-finish-load", function () {
// 恢复上一次的位置
let bounds = cacheData.cacheStore.get("searchWindowBounds");
if (bounds != null) {
searchWindow.setBounds({ x: bounds.x, y: bounds.y });
}
// 设置可以显示
global.searchWindowShow = true;
});
// 隐藏窗口
searchWindow.on("hide", () => {
searchWindow.setBounds({ height: 44 });
searchWindow.webContents.send("hideSearchWindowOperation");
});
// 显示窗口
searchWindow.on("show", () => {
searchWindow.setBackgroundColor(global.setting.appearance.theme.mainBackground.replace("bg-[", "").replace("]", ""));
// 显示窗口时将输入法切换为英文模式
if (global.setting.general.switchEnglish) {
global.api.SwitchEnglish(searchWindow.getNativeWindowHandle());
}
});
// 窗口移动完毕
searchWindow.on("moved", () => {
// 记录位置
cacheData.cacheStore.set("searchWindowBounds", searchWindow.getBounds());
});
// 失去焦点
searchWindow.on("blur", () => {
if (searchWindow.isVisible() && global.setting.quickSearch.hideLosingFocus) {
global.searchWindow.webContents.send("hideSearchWindowBefore");
}
});
// 禁用标题栏右键
searchWindow.hookWindowMessage(278, function (e) {
// 窗口禁用
searchWindow.setEnabled(false);
// 延时太快会立刻启动,太慢会妨碍窗口其他操作,可自行测试最佳时间
setTimeout(() => {
searchWindow.setEnabled(true);
}, 100);
return true;
});
}
/**
* 自动隐藏
* @param data
* @param size
* @param timer
*/
function autoHide(data, size, timer) {
if (global.mainWindow.isDestroyed()) {
return;
}
try {
let displays = util.getWindowInScreen();
if (displays.length > 1 || displays.length == 0) {
return;
}
let workArea = displays[0].workArea;
let scaleFactor = displays[0].scaleFactor;
let bounds = mainWindow.getBounds();
if (mainWindow.isVisible()) {
let flag = false;
if (bounds.x + bounds.width >= workArea.x + workArea.width) {
// 右侧
flag = data.x <= bounds.x * scaleFactor - size || data.y <= bounds.y * scaleFactor - size || data.y >= (bounds.y + bounds.height) * scaleFactor + size;
} else if (bounds.x == workArea.x) {
// 左侧
flag =
data.x > (bounds.x + bounds.width) * scaleFactor + size ||
data.y <= bounds.y * scaleFactor - size ||
data.y >= (bounds.y + bounds.height) * scaleFactor + size;
} else if (bounds.y + bounds.height >= workArea.y + workArea.height) {
// 底部
flag = data.y < bounds.y * scaleFactor - size || data.x <= bounds.x * scaleFactor - size || data.x >= (bounds.x + bounds.width) * scaleFactor + size;
} else if (bounds.y == workArea.y) {
// 顶部
flag =
data.y > (bounds.y + bounds.height) * scaleFactor + size ||
data.x <= bounds.x * scaleFactor - size ||
data.x >= (bounds.x + bounds.width) * scaleFactor + size;
}
if (flag) {
if (global.menuShow != null && global.menuShow) {
return;
}
if (timer && global.setting.general.delayHidingMS > 0 && global.autoHideTimer == null) {
global.autoHideTimer = setTimeout(function () {
// 隐藏
// mainWindow.hide();
global.mainWindow.webContents.send("hideMainWindowBefore");
}, global.setting.general.delayHidingMS);
} else if (global.setting.general.delayHidingMS == 0 || !timer) {
// 隐藏
// mainWindow.hide();
global.mainWindow.webContents.send("hideMainWindowBefore");
}
} else {
clearTimeout(global.autoHideTimer);
global.autoHideTimer = null;
}
} else {
if (global.direction != "none") {
let flag = false;
let x = bounds.x * scaleFactor;
let y = bounds.y * scaleFactor;
let windowWidthPosition = (bounds.x + bounds.width) * scaleFactor;
let windowHeightPosition = (bounds.y + bounds.height) * scaleFactor;
if (global.direction == "right" && data.x >= windowWidthPosition - 1 && data.y >= y && data.y <= windowHeightPosition) {
// 右侧
flag = true;
} else if (global.direction == "left" && data.x <= workArea.x && data.y >= y && data.y <= windowHeightPosition) {
// 左侧
flag = true;
} else if (global.direction == "bottom" && data.y >= windowHeightPosition - 1 && data.x >= x && data.x <= windowWidthPosition) {
// 底部
flag = true;
} else if (global.direction == "top" && data.y <= workArea.y && data.x >= x && data.x <= windowWidthPosition) {
// 顶部
flag = true;
}
if (flag) {
if (util.notDisturb()) {
return;
}
if (timer && global.setting.general.delayDisplayMS > 0 && global.autoHideTimer == null) {
global.autoHideTimer = setTimeout(function () {
// 显示
mainWindow.show();
if (!global.setting.general.alwaysTop) {
global.mainWindow.setAlwaysOnTop(true, "screen-saver");
global.mainWindow.setAlwaysOnTop(false);
}
}, global.setting.general.delayDisplayMS);
} else if (global.setting.general.delayDisplayMS == 0 || !timer) {
// 显示
mainWindow.show();
if (!global.setting.general.alwaysTop) {
global.mainWindow.setAlwaysOnTop(true, "screen-saver");
global.mainWindow.setAlwaysOnTop(false);
}
}
} else {
clearTimeout(global.autoHideTimer);
global.autoHideTimer = null;
}
}
}
} catch (e) {
if (process.env.NODE_ENV !== "production") {
console.log(e);
}
global.mainWindow.setBounds({ x: 1, y: 1 });
}
}
/**
* 显示设置窗口
*/
function showSettingWindow() {
if (settingWindow != null && !settingWindow.isDestroyed()) {
if (!settingWindow.isVisible()) {
settingWindow.show();
}
settingWindow.focus();
} else {
createSettingWindow();
}
}
app.whenReady().then(() => {
// 禁用debugtron
for (let i = 0; i < process.argv.length; i++) {
const arg = process.argv[i];
if (arg.indexOf("--inspect") !== -1 || arg.indexOf("--remote-debugging-port") !== -1) {
dialog.showMessageBoxSync(global.mainWindow, {
title: "Dawn Launcher",
message: "达咩呦达咩达咩~",
buttons: ["确定"],
type: "error",
noLink: true,
});
app.quit();
return;
}
}
// 禁止多开
const instanceLock = app.requestSingleInstanceLock();
if (!instanceLock) {
app.quit();
return;
}
// 设置快捷键
let setting = settingData.get();
settingIndex.setShortcutKey(setting);
// 引用c++
try {
global.api = require("bindings")({
bindings: "api.node",
module_root: process.env.NODE_ENV !== "production" ? path.resolve(".") : path.dirname(process.execPath),
});
} catch (e) {
dialog.showMessageBoxSync(global.mainWindow, {
title: "Dawn Launcher",
message: "缺少DLL文件请重新下载安装包安装后运行。",
buttons: ["确定"],
type: "error",
noLink: true,
});
app.quit();
return;
}
// 创建窗口
createWindow(true);
});
app.on("second-instance", (event, commandLine, workingDirectory) => {
if (mainWindow) {
if (!mainWindow.isVisible()) {
mainWindow.show();
mainWindow.focus();
global.blurHide = true;
} else {
mainWindow.focus();
}
}
});
app.on("window-all-closed", () => {
// 释放鼠标监听
global.api.disableMouseMove();
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow(false).then((r) => {});
}
});
if (process.env.NODE_ENV === "production") {
// 开机启动
const exeName = path.basename(process.execPath);
ipcMain.on("setAutoLaunch", (event, args) => {
app.setLoginItemSettings({
openAtLogin: args,
openAsHidden: false,
path: process.execPath,
args: ["--processStart", `"${exeName}"`],
});
});
}
// 设置当前语言
ipcMain.on("setCurrentLanguage", (event, args) => {
let currentLanguage = JSON.parse(args);
global.currentLanguage = currentLanguage;
// 托盘菜单
setTray(!global.setting.general.hideTray);
});
/**
* 托盘
*/
function setTray(show) {
// 获取语言
if (show) {
if (global.tray == null) {
// 环境判断
if (process.env.NODE_ENV !== "production") {
// 开发
global.tray = new Tray("./public/images/logo-thick.ico");
} else {
// 正式
global.tray = new Tray(path.join(__dirname, "./images/logo-thick.ico"));
}
}
let contextMenu = Menu.buildFromTemplate([
{
label: global.currentLanguage.displayMainInterface,
click: function () {
mainWindow.show();
global.blurHide = true;
},
},
{
label: global.currentLanguage.setting,
click: function () {
showSettingWindow();
},
},
{
// 点击退出菜单退出程序
label: global.currentLanguage.exit,
click: function () {
mainWindow.close();
},
},
]);
// 托盘
global.tray.setToolTip("Dawn Launcher");
global.tray.setContextMenu(contextMenu);
// 点击托盘图标,显示主窗口
global.tray.on("click", () => {
mainWindow.show();
global.blurHide = true;
});
} else {
// 隐藏托盘
if (global.tray != null) {
if (!global.tray.isDestroyed()) {
global.tray.destroy();
global.tray = null;
}
}
}
}
// 创建搜索窗口
ipcMain.on("createSearchWindow", () => {
// 搜索框
createSearchWindow();
});
// 托盘
ipcMain.on("setTray", (event, args) => {
setTray(args);
});
// 开启快捷搜索
ipcMain.on("setEnableQuickSearch", (event, args) => {
// 设置快捷键
let setting = settingData.get();
setting.quickSearch.enable = args;
settingIndex.setShortcutKey(setting);
});
// 设置背景透明度
ipcMain.on("setBackgroundTransparency", (event, args) => {
if ((Number(args) == 1 && global.backgroundTransparency) || (Number(args) != 1 && !global.backgroundTransparency)) {
mainWindow.destroy();
global.mainWindow = mainWindow = null;
createWindow(false);
}
});
// 创建设置窗口
ipcMain.on("createSettingWindow", (event, args) => {
showSettingWindow();
});
// 显示搜索窗口
ipcMain.on("searchWindowShow", (event, args) => {
if (args != null) {
searchWindow.setBounds({ height: args });
}
searchWindow.show();
});