mirror of
https://github.com/rubickCenter/rubick
synced 2025-06-06 10:34:08 +08:00
390 lines
11 KiB
TypeScript
390 lines
11 KiB
TypeScript
import {
|
|
BrowserWindow,
|
|
ipcMain,
|
|
dialog,
|
|
app,
|
|
Notification,
|
|
nativeImage,
|
|
clipboard,
|
|
screen,
|
|
shell,
|
|
} from 'electron';
|
|
import fs from 'fs';
|
|
import { screenCapture } from '@/core';
|
|
import plist from 'plist';
|
|
import ks from 'node-key-sender';
|
|
|
|
import {
|
|
DECODE_KEY,
|
|
PLUGIN_INSTALL_DIR as baseDir,
|
|
} from '@/common/constans/main';
|
|
import getCopyFiles from '@/common/utils/getCopyFiles';
|
|
import common from '@/common/utils/commonConst';
|
|
|
|
import mainInstance from '../index';
|
|
import { runner, detach } from '../browsers';
|
|
import DBInstance from './db';
|
|
import getWinPosition from './getWinPosition';
|
|
import path from 'path';
|
|
import commonConst from '@/common/utils/commonConst';
|
|
|
|
const runnerInstance = runner();
|
|
const detachInstance = detach();
|
|
|
|
class API extends DBInstance {
|
|
init(mainWindow: BrowserWindow) {
|
|
// 响应 preload.js 事件
|
|
ipcMain.on('msg-trigger', async (event, arg) => {
|
|
const window = arg.winId ? BrowserWindow.fromId(arg.winId) : mainWindow;
|
|
const data = await this[arg.type](arg, window, event);
|
|
event.returnValue = data;
|
|
// event.sender.send(`msg-back-${arg.type}`, data);
|
|
});
|
|
// 按 ESC 退出插件
|
|
mainWindow.webContents.on('before-input-event', (event, input) =>
|
|
this.__EscapeKeyDown(event, input, mainWindow)
|
|
);
|
|
}
|
|
|
|
public getCurrentWindow = (window, e) => {
|
|
let originWindow = BrowserWindow.fromWebContents(e.sender);
|
|
if (originWindow !== window) originWindow = detachInstance.getWindow();
|
|
return originWindow;
|
|
};
|
|
|
|
public __EscapeKeyDown = (event, input, window) => {
|
|
if (input.type !== 'keyDown') return;
|
|
if (!(input.meta || input.control || input.shift || input.alt)) {
|
|
if (input.key === 'Escape') {
|
|
if (this.currentPlugin) {
|
|
this.removePlugin(null, window);
|
|
} else {
|
|
mainInstance.windowCreator.getWindow().hide();
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
};
|
|
|
|
public windowMoving({ data: { mouseX, mouseY, width, height } }, window, e) {
|
|
const { x, y } = screen.getCursorScreenPoint();
|
|
const originWindow = this.getCurrentWindow(window, e);
|
|
if (!originWindow) return;
|
|
originWindow.setBounds({ x: x - mouseX, y: y - mouseY, width, height });
|
|
getWinPosition.setPosition(x - mouseX, y - mouseY);
|
|
}
|
|
|
|
public loadPlugin({ data: plugin }, window) {
|
|
window.webContents.executeJavaScript(
|
|
`window.loadPlugin(${JSON.stringify(plugin)})`
|
|
);
|
|
this.openPlugin({ data: plugin }, window);
|
|
}
|
|
|
|
public openPlugin({ data: plugin }, window) {
|
|
if (plugin.platform && !plugin.platform.includes(process.platform)) {
|
|
return new Notification({
|
|
title: `插件不支持当前 ${process.platform} 系统`,
|
|
body: `插件仅支持 ${plugin.platform.join(',')}`,
|
|
icon: plugin.logo,
|
|
}).show();
|
|
}
|
|
window.setSize(window.getSize()[0], 60);
|
|
this.removePlugin(null, window);
|
|
// 模板文件
|
|
if (!plugin.main) {
|
|
plugin.tplPath = common.dev()
|
|
? 'http://localhost:8083/#/'
|
|
: `file://${__static}/tpl/index.html`;
|
|
}
|
|
if (plugin.name === 'rubick-system-feature') {
|
|
plugin.logo = plugin.logo || `file://${__static}/logo.png`;
|
|
plugin.indexPath = commonConst.dev()
|
|
? 'http://localhost:8081/#/'
|
|
: `file://${__static}/feature/index.html`;
|
|
} else if (!plugin.indexPath) {
|
|
const pluginPath = path.resolve(baseDir, 'node_modules', plugin.name);
|
|
plugin.indexPath = `file://${path.join(
|
|
pluginPath,
|
|
'./',
|
|
plugin.main || ''
|
|
)}`;
|
|
}
|
|
runnerInstance.init(plugin, window);
|
|
this.currentPlugin = plugin;
|
|
window.webContents.executeJavaScript(
|
|
`window.setCurrentPlugin(${JSON.stringify({
|
|
currentPlugin: this.currentPlugin,
|
|
})})`
|
|
);
|
|
window.show();
|
|
const view = runnerInstance.getView();
|
|
if (!view.inited) {
|
|
view.webContents.on('before-input-event', (event, input) =>
|
|
this.__EscapeKeyDown(event, input, window)
|
|
);
|
|
}
|
|
}
|
|
|
|
public removePlugin(e, window) {
|
|
this.currentPlugin = null;
|
|
runnerInstance.removeView(window);
|
|
}
|
|
|
|
public openPluginDevTools() {
|
|
runnerInstance.getView().webContents.openDevTools({ mode: 'detach' });
|
|
}
|
|
|
|
public hideMainWindow(arg, window) {
|
|
window.hide();
|
|
}
|
|
|
|
public showMainWindow(arg, window) {
|
|
window.show();
|
|
}
|
|
|
|
public showOpenDialog({ data }, window) {
|
|
return dialog.showOpenDialogSync(window, data);
|
|
}
|
|
|
|
public showSaveDialog({ data }, window) {
|
|
return dialog.showSaveDialogSync(window, data);
|
|
}
|
|
|
|
public setExpendHeight({ data: height }, window: BrowserWindow, e) {
|
|
const originWindow = this.getCurrentWindow(window, e);
|
|
if (!originWindow) return;
|
|
const targetHeight = height;
|
|
originWindow.setSize(originWindow.getSize()[0], targetHeight);
|
|
const screenPoint = screen.getCursorScreenPoint();
|
|
const display = screen.getDisplayNearestPoint(screenPoint);
|
|
const position =
|
|
originWindow.getPosition()[1] + targetHeight > display.bounds.height
|
|
? height - 60
|
|
: 0;
|
|
originWindow.webContents.executeJavaScript(
|
|
`window.setPosition && typeof window.setPosition === "function" && window.setPosition(${position})`
|
|
);
|
|
}
|
|
|
|
public setSubInput({ data }, window, e) {
|
|
const originWindow = this.getCurrentWindow(window, e);
|
|
if (!originWindow) return;
|
|
originWindow.webContents.executeJavaScript(
|
|
`window.setSubInput(${JSON.stringify({
|
|
placeholder: data.placeholder,
|
|
})})`
|
|
);
|
|
}
|
|
|
|
public subInputBlur() {
|
|
runnerInstance.getView().webContents.focus();
|
|
}
|
|
|
|
public sendSubInputChangeEvent({ data }) {
|
|
runnerInstance.executeHooks('SubInputChange', data);
|
|
}
|
|
|
|
public removeSubInput(data, window, e) {
|
|
const originWindow = this.getCurrentWindow(window, e);
|
|
if (!originWindow) return;
|
|
originWindow.webContents.executeJavaScript(`window.removeSubInput()`);
|
|
}
|
|
|
|
public setSubInputValue({ data }, window, e) {
|
|
const originWindow = this.getCurrentWindow(window, e);
|
|
if (!originWindow) return;
|
|
originWindow.webContents.executeJavaScript(
|
|
`window.setSubInputValue(${JSON.stringify({
|
|
value: data.text,
|
|
})})`
|
|
);
|
|
this.sendSubInputChangeEvent({ data });
|
|
}
|
|
|
|
public getPath({ data }) {
|
|
return app.getPath(data.name);
|
|
}
|
|
|
|
public showNotification({ data: { body } }) {
|
|
if (!Notification.isSupported()) return;
|
|
'string' != typeof body && (body = String(body));
|
|
const plugin = this.currentPlugin;
|
|
if (!plugin) return;
|
|
const notify = new Notification({
|
|
title: plugin.pluginName,
|
|
body,
|
|
icon: plugin.logo,
|
|
});
|
|
notify.show();
|
|
}
|
|
|
|
public copyImage = ({ data }) => {
|
|
const image = nativeImage.createFromDataURL(data.img);
|
|
clipboard.writeImage(image);
|
|
};
|
|
|
|
public copyText({ data }) {
|
|
clipboard.writeText(String(data.text));
|
|
return true;
|
|
}
|
|
|
|
public copyFile({ data }) {
|
|
if (data.file && fs.existsSync(data.file)) {
|
|
clipboard.writeBuffer(
|
|
'NSFilenamesPboardType',
|
|
Buffer.from(plist.build([data.file]))
|
|
);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public getFeatures() {
|
|
return this.currentPlugin?.features;
|
|
}
|
|
|
|
public setFeature({ data }, window) {
|
|
this.currentPlugin = {
|
|
...this.currentPlugin,
|
|
features: (() => {
|
|
let has = false;
|
|
this.currentPlugin.features.some((feature) => {
|
|
has = feature.code === data.feature.code;
|
|
return has;
|
|
});
|
|
if (!has) {
|
|
return [...this.currentPlugin.features, data.feature];
|
|
}
|
|
return this.currentPlugin.features;
|
|
})(),
|
|
};
|
|
window.webContents.executeJavaScript(
|
|
`window.updatePlugin(${JSON.stringify({
|
|
currentPlugin: this.currentPlugin,
|
|
})})`
|
|
);
|
|
return true;
|
|
}
|
|
|
|
public removeFeature({ data }, window) {
|
|
this.currentPlugin = {
|
|
...this.currentPlugin,
|
|
features: this.currentPlugin.features.filter((feature) => {
|
|
if (data.code.type) {
|
|
return feature.code.type !== data.code.type;
|
|
}
|
|
return feature.code !== data.code;
|
|
}),
|
|
};
|
|
window.webContents.executeJavaScript(
|
|
`window.updatePlugin(${JSON.stringify({
|
|
currentPlugin: this.currentPlugin,
|
|
})})`
|
|
);
|
|
return true;
|
|
}
|
|
|
|
public sendPluginSomeKeyDownEvent({ data: { modifiers, keyCode } }) {
|
|
const code = DECODE_KEY[keyCode];
|
|
if (!code || !runnerInstance.getView()) return;
|
|
if (modifiers.length > 0) {
|
|
runnerInstance.getView().webContents.sendInputEvent({
|
|
type: 'keyDown',
|
|
modifiers,
|
|
keyCode: code,
|
|
});
|
|
} else {
|
|
runnerInstance.getView().webContents.sendInputEvent({
|
|
type: 'keyDown',
|
|
keyCode: code,
|
|
});
|
|
}
|
|
}
|
|
|
|
public detachPlugin(e, window) {
|
|
if (!this.currentPlugin) return;
|
|
const view = window.getBrowserView();
|
|
window.setBrowserView(null);
|
|
window.webContents
|
|
.executeJavaScript(`window.getMainInputInfo()`)
|
|
.then((res) => {
|
|
detachInstance.init(
|
|
{
|
|
...this.currentPlugin,
|
|
subInput: res,
|
|
},
|
|
window.getBounds(),
|
|
view
|
|
);
|
|
window.webContents.executeJavaScript(`window.initRubick()`);
|
|
window.setSize(window.getSize()[0], 60);
|
|
this.currentPlugin = null;
|
|
});
|
|
}
|
|
|
|
public detachInputChange({ data }) {
|
|
this.sendSubInputChangeEvent({ data });
|
|
}
|
|
|
|
public getLocalId() {
|
|
return encodeURIComponent(app.getPath('home'));
|
|
}
|
|
|
|
public shellShowItemInFolder({ data }) {
|
|
shell.showItemInFolder(data.path);
|
|
return true;
|
|
}
|
|
|
|
public async getFileIcon({ data }) {
|
|
const nativeImage = await app.getFileIcon(data.path, { size: 'normal' });
|
|
return nativeImage.toDataURL();
|
|
}
|
|
|
|
public shellBeep() {
|
|
shell.beep();
|
|
return true;
|
|
}
|
|
|
|
public screenCapture(arg, window) {
|
|
screenCapture(window, (img) => {
|
|
runnerInstance.executeHooks('ScreenCapture', {
|
|
data: img,
|
|
});
|
|
});
|
|
}
|
|
|
|
public getCopyFiles() {
|
|
return getCopyFiles();
|
|
}
|
|
|
|
public simulateKeyboardTap({ data: { key, modifier } }) {
|
|
let keys = [key.toLowerCase()];
|
|
if (modifier && Array.isArray(modifier) && modifier.length > 0) {
|
|
keys = modifier.concat(keys);
|
|
ks.sendCombination(keys);
|
|
} else {
|
|
ks.sendKeys(keys);
|
|
}
|
|
}
|
|
|
|
public addLocalStartPlugin({ data: { plugin } }, window) {
|
|
window.webContents.executeJavaScript(
|
|
`window.addLocalStartPlugin(${JSON.stringify({
|
|
plugin,
|
|
})})`
|
|
);
|
|
}
|
|
|
|
public removeLocalStartPlugin({ data: { plugin } }, window) {
|
|
window.webContents.executeJavaScript(
|
|
`window.removeLocalStartPlugin(${JSON.stringify({
|
|
plugin,
|
|
})})`
|
|
);
|
|
}
|
|
}
|
|
|
|
export default new API();
|