🔨 resolve conflicts

This commit is contained in:
layyback
2023-03-26 19:46:46 +08:00
52 changed files with 10156 additions and 739 deletions

View File

@@ -16,7 +16,7 @@ export default function getCopyFiles(): Array<any> | null {
} catch (e) {
return null;
}
} else if (commonConst.windows()) {
} else if (process.platform === "win32") {
/* eslint-disable */
const clipboardEx = require("electron-clipboard-ex");
fileInfo = clipboardEx.readFilePaths();

View File

@@ -1,14 +1,14 @@
import {
AdapterHandlerOptions,
AdapterInfo,
} from "@/core/plugin-handler/types";
import fs from "fs-extra";
import path from "path";
import got from "got";
import fixPath from "fix-path";
} from '@/core/plugin-handler/types';
import fs from 'fs-extra';
import path from 'path';
import got from 'got';
import fixPath from 'fix-path';
import spawn from "cross-spawn";
import { ipcRenderer } from "electron";
import spawn from 'cross-spawn';
import { ipcRenderer } from 'electron';
fixPath();
@@ -38,18 +38,18 @@ class AdapterHandler {
}
this.baseDir = options.baseDir;
let register = options.registry || "https://registry.npm.taobao.org";
let register = options.registry || 'https://registry.npm.taobao.org';
try {
const dbdata = ipcRenderer.sendSync("msg-trigger", {
type: "dbGet",
data: { id: "rubick-localhost-config" },
const dbdata = ipcRenderer.sendSync('msg-trigger', {
type: 'dbGet',
data: { id: 'rubick-localhost-config' },
});
register = dbdata.data.register;
} catch (e) {
// ignore
}
this.registry = register || "https://registry.npm.taobao.org";
this.registry = register || 'https://registry.npm.taobao.org';
}
/**
@@ -65,11 +65,11 @@ class AdapterHandler {
let adapterInfo: AdapterInfo;
const infoPath =
adapterPath ||
path.resolve(this.baseDir, "node_modules", adapter, "plugin.json");
path.resolve(this.baseDir, 'node_modules', adapter, 'plugin.json');
// 从本地获取
if (await fs.pathExists(infoPath)) {
adapterInfo = JSON.parse(
fs.readFileSync(infoPath, "utf-8")
fs.readFileSync(infoPath, 'utf-8')
) as AdapterInfo;
} else {
// 本地没有从远程获取
@@ -84,7 +84,7 @@ class AdapterHandler {
// 安装并启动插件
async install(adapters: Array<string>, options: { isDev: boolean }) {
const installCmd = options.isDev ? "link" : "install";
const installCmd = options.isDev ? 'link' : 'install';
// 安装
await this.execCommand(installCmd, adapters);
}
@@ -95,7 +95,7 @@ class AdapterHandler {
* @memberof AdapterHandler
*/
async update(...adapters: string[]) {
await this.execCommand("update", adapters);
await this.execCommand('update', adapters);
}
/**
@@ -105,7 +105,7 @@ class AdapterHandler {
* @memberof AdapterHandler
*/
async uninstall(adapters: string[], options: { isDev: boolean }) {
const installCmd = options.isDev ? "unlink" : "uninstall";
const installCmd = options.isDev ? 'unlink' : 'uninstall';
// 卸载插件
await this.execCommand(installCmd, adapters);
}
@@ -116,7 +116,7 @@ class AdapterHandler {
*/
async list() {
const installInfo = JSON.parse(
await fs.readFile(`${this.baseDir}/package.json`, "utf-8")
await fs.readFile(`${this.baseDir}/package.json`, 'utf-8')
);
const adapters: string[] = [];
for (const adapter in installInfo.dependencies) {
@@ -124,37 +124,45 @@ class AdapterHandler {
}
return adapters;
}
private cleanCache() {
spawn('npm', ['cache', 'clean', '-f'], {
cwd: this.baseDir,
});
}
/**
* 运行包管理器
* @memberof AdapterHandler
*/
private async execCommand(cmd: string, modules: string[]): Promise<string> {
this.cleanCache();
return new Promise((resolve: any, reject: any) => {
let args: string[] = [cmd]
.concat(modules)
.concat("--color=always")
.concat("--save");
if (cmd !== "uninstall")
.concat(
cmd !== 'uninstall' ? modules.map((m) => `${m}@latest`) : modules
)
.concat('--color=always')
.concat('--save');
if (cmd !== 'uninstall')
args = args.concat(`--registry=${this.registry}`);
const npm = spawn("npm", args, {
const npm = spawn('npm', args, {
cwd: this.baseDir,
});
let output = "";
let output = '';
npm.stdout
.on("data", (data: string) => {
.on('data', (data: string) => {
output += data; // 获取输出日志
})
.pipe(process.stdout);
npm.stderr
.on("data", (data: string) => {
.on('data', (data: string) => {
output += data; // 获取报错日志
})
.pipe(process.stderr);
npm.on("close", (code: number) => {
npm.on('close', (code: number) => {
if (!code) {
resolve({ code: 0, data: output }); // 如果没有报错就输出正常日志
} else {

View File

@@ -1,5 +1,5 @@
import { app, BrowserWindow, protocol } from "electron";
import path from "path";
import { app, BrowserWindow, protocol } from 'electron';
import path from 'path';
export default () => {
let win: any;
@@ -12,7 +12,7 @@ export default () => {
height: viewInfo.height,
width: viewInfo.width,
autoHideMenuBar: true,
titleBarStyle: "hidden",
titleBarStyle: 'hidden',
trafficLightPosition: { x: 12, y: 21 },
title: pluginInfo.pluginName,
resizable: true,
@@ -32,22 +32,34 @@ export default () => {
});
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
win.loadURL("http://localhost:8082");
win.loadURL('http://localhost:8082');
} else {
win.loadURL(`file://${path.join(__static, "./detach/index.html")}`);
win.loadURL(`file://${path.join(__static, './detach/index.html')}`);
}
win.on("closed", () => {
win.on('close', () => {
executeHooks('PluginOut', null);
});
win.on('closed', () => {
win = undefined;
});
win.once("ready-to-show", () => {
win.once('ready-to-show', () => {
win.setBrowserView(view);
win.webContents.executeJavaScript(
`window.initDetach(${JSON.stringify(pluginInfo)})`
);
win.show();
});
const executeHooks = (hook, data) => {
if (!view) return;
const evalJs = `console.log(window.rubick);if(window.rubick && window.rubick.hooks && typeof window.rubick.hooks.on${hook} === 'function' ) {
try {
window.rubick.hooks.on${hook}(${data ? JSON.stringify(data) : ''});
} catch(e) {console.log(e)}
}
`;
view.webContents.executeJavaScript(evalJs);
};
};
const getWindow = () => win;

View File

@@ -1,19 +1,19 @@
import { BrowserView, BrowserWindow, session } from "electron";
import path from "path";
import commonConst from "../../common/utils/commonConst";
import { PLUGIN_INSTALL_DIR as baseDir } from "@/common/constans/main";
import { BrowserView, BrowserWindow, session } from 'electron';
import path from 'path';
import commonConst from '../../common/utils/commonConst';
import { PLUGIN_INSTALL_DIR as baseDir } from '@/common/constans/main';
const getRelativePath = indexPath => {
const getRelativePath = (indexPath) => {
return commonConst.windows()
? indexPath.replace("file://", "")
: indexPath.replace("file:", "");
? indexPath.replace('file://', '')
: indexPath.replace('file:', '');
};
const getPreloadPath = (plugin, pluginIndexPath) => {
const { name, preload, tplPath, indexPath } = plugin;
if (!preload) return;
if (commonConst.dev()) {
if (name === "rubick-system-feature") {
if (name === 'rubick-system-feature') {
return path.resolve(__static, `../feature/public/preload.js`);
}
if (tplPath) {
@@ -37,15 +37,30 @@ export default () => {
};
const createView = (plugin, window: BrowserWindow) => {
let pluginIndexPath = plugin.tplPath || plugin.indexPath;
const { tplPath, indexPath, development, name, main, pluginSetting, ext } =
plugin;
let pluginIndexPath = tplPath || indexPath;
let preloadPath;
let darkMode;
if (!pluginIndexPath) {
const pluginPath = path.resolve(baseDir, "node_modules", plugin.name);
pluginIndexPath = `file://${path.join(pluginPath, "./", plugin.main)}`;
// 开发环境
if (commonConst.dev() && development) {
pluginIndexPath = development;
const pluginPath = path.resolve(baseDir, 'node_modules', name);
preloadPath = `file://${path.join(pluginPath, './', main)}`;
}
const preload = getPreloadPath(plugin, pluginIndexPath);
// 再尝试去找
if (plugin.name === 'rubick-system-feature' && !pluginIndexPath) {
pluginIndexPath = commonConst.dev()
? 'http://localhost:8081/#/'
: `file://${__static}/feature/index.html`;
}
if (!pluginIndexPath) {
const pluginPath = path.resolve(baseDir, 'node_modules', name);
pluginIndexPath = `file://${path.join(pluginPath, './', main)}`;
}
const preload = getPreloadPath(plugin, preloadPath || pluginIndexPath);
const ses = session.fromPartition("<" + plugin.name + ">");
const ses = session.fromPartition('<' + name + '>');
ses.setPreloads([`${__static}/preload.js`]);
view = new BrowserView({
@@ -57,17 +72,18 @@ export default () => {
devTools: true,
webviewTag: true,
preload,
session: ses
}
session: ses,
},
});
window.setBrowserView(view);
view.webContents.loadURL(pluginIndexPath);
view.webContents.once("dom-ready", () => {
window.setSize(800, 660);
view.setBounds({ x: 0, y: 60, width: 800, height: 600 });
view.webContents.once('dom-ready', () => {
const height = pluginSetting && pluginSetting.height;
window.setSize(800, height || 660);
view.setBounds({ x: 0, y: 60, width: 800, height: height || 660 });
view.setAutoResize({ width: true });
executeHooks("PluginEnter", plugin.ext);
executeHooks("PluginReady", plugin.ext);
executeHooks('PluginEnter', plugin.ext);
executeHooks('PluginReady', plugin.ext);
darkMode = global.OP_CONFIG.get().perf.common.darkMode;
darkMode &&
view.webContents.executeJavaScript(
@@ -79,7 +95,7 @@ export default () => {
view.webContents.session.webRequest.onBeforeSendHeaders(
(details, callback) => {
callback({
requestHeaders: { referer: "*", ...details.requestHeaders }
requestHeaders: { referer: '*', ...details.requestHeaders },
});
}
);
@@ -88,9 +104,9 @@ export default () => {
(details, callback) => {
callback({
responseHeaders: {
"Access-Control-Allow-Origin": ["*"],
...details.responseHeaders
}
'Access-Control-Allow-Origin': ['*'],
...details.responseHeaders,
},
});
}
);
@@ -100,7 +116,7 @@ export default () => {
if (!view) return;
window.removeBrowserView(view);
window.setSize(800, 60);
executeHooks("PluginOut", null);
executeHooks('PluginOut', null);
window.webContents.executeJavaScript(`window.initRubick()`);
view = undefined;
};
@@ -111,7 +127,7 @@ export default () => {
if (!view) return;
const evalJs = `if(window.rubick && window.rubick.hooks && typeof window.rubick.hooks.on${hook} === 'function' ) {
try {
window.rubick.hooks.on${hook}(${data ? JSON.stringify(data) : ""});
window.rubick.hooks.on${hook}(${data ? JSON.stringify(data) : ''});
} catch(e) {}
}
`;
@@ -122,6 +138,6 @@ export default () => {
init,
getView,
removeView,
executeHooks
executeHooks,
};
};

View File

@@ -6,27 +6,27 @@ import {
Notification,
nativeImage,
clipboard,
shell
} from "electron";
import { runner, detach } from "../browsers";
import fs from "fs";
import { LocalDb } from "@/core";
import plist from "plist";
import { DECODE_KEY } from "@/common/constans/main";
import mainInstance from "../index";
shell,
} from 'electron';
import { runner, detach } from '../browsers';
import fs from 'fs';
import { LocalDb } from '@/core';
import plist from 'plist';
import { DECODE_KEY } from '@/common/constans/main';
import mainInstance from '../index';
const runnerInstance = runner();
const detachInstance = detach();
const dbInstance = new LocalDb(app.getPath("userData"));
const dbInstance = new LocalDb(app.getPath('userData'));
dbInstance.init();
class API {
public currentPlugin: null | any = null;
private DBKEY = "RUBICK_DB_DEFAULT";
private DBKEY = 'RUBICK_DB_DEFAULT';
init(mainWindow: BrowserWindow) {
// 响应 preload.js 事件
ipcMain.on("msg-trigger", async (event, arg) => {
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;
@@ -41,9 +41,9 @@ class API {
};
public __EscapeKeyDown = (event, input, window) => {
if (input.type !== "keyDown") return;
if (input.type !== 'keyDown') return;
if (!(input.meta || input.control || input.shift || input.alt)) {
if (input.key === "Escape") {
if (input.key === 'Escape') {
if (this.currentPlugin) {
this.removePlugin(null, window);
} else {
@@ -70,17 +70,17 @@ class API {
this.currentPlugin = plugin;
window.webContents.executeJavaScript(
`window.setCurrentPlugin(${JSON.stringify({
currentPlugin: this.currentPlugin
currentPlugin: this.currentPlugin,
})})`
);
window.show();
// 按 ESC 退出插件
window.webContents.on("before-input-event", (event, input) =>
window.webContents.on('before-input-event', (event, input) =>
this.__EscapeKeyDown(event, input, window)
);
runnerInstance
.getView()
.webContents.on("before-input-event", (event, input) =>
.webContents.on('before-input-event', (event, input) =>
this.__EscapeKeyDown(event, input, window)
);
}
@@ -91,7 +91,7 @@ class API {
}
public openPluginDevTools() {
runnerInstance.getView().webContents.openDevTools({ mode: "detach" });
runnerInstance.getView().webContents.openDevTools({ mode: 'detach' });
}
public hideMainWindow(arg, window) {
@@ -118,7 +118,7 @@ class API {
if (!originWindow) return;
originWindow.webContents.executeJavaScript(
`window.setSubInput(${JSON.stringify({
placeholder: data.placeholder
placeholder: data.placeholder,
})})`
);
}
@@ -128,7 +128,7 @@ class API {
}
public sendSubInputChangeEvent({ data }) {
runnerInstance.executeHooks("SubInputChange", data);
runnerInstance.executeHooks('SubInputChange', data);
}
public removeSubInput(data, window, e) {
@@ -142,7 +142,7 @@ class API {
if (!originWindow) return;
originWindow.webContents.executeJavaScript(
`window.setSubInputValue(${JSON.stringify({
value: data.text
value: data.text,
})})`
);
}
@@ -153,13 +153,13 @@ class API {
public showNotification({ data: { body } }) {
if (!Notification.isSupported()) return;
"string" != typeof body && (body = String(body));
'string' != typeof body && (body = String(body));
const plugin = this.currentPlugin;
if (!plugin) return;
const notify = new Notification({
title: plugin.pluginName,
body,
icon: plugin.logo
icon: plugin.logo,
});
notify.show();
}
@@ -177,7 +177,7 @@ class API {
public copyFile({ data }) {
if (data.file && fs.existsSync(data.file)) {
clipboard.writeBuffer(
"NSFilenamesPboardType",
'NSFilenamesPboardType',
Buffer.from(plist.build([data.file]))
);
return true;
@@ -214,7 +214,7 @@ class API {
...this.currentPlugin,
features: (() => {
let has = false;
this.currentPlugin.features.some(feature => {
this.currentPlugin.features.some((feature) => {
has = feature.code === data.feature.code;
return has;
});
@@ -222,11 +222,11 @@ class API {
return [...this.currentPlugin.features, data.feature];
}
return this.currentPlugin.features;
})()
})(),
};
window.webContents.executeJavaScript(
`window.updatePlugin(${JSON.stringify({
currentPlugin: this.currentPlugin
currentPlugin: this.currentPlugin,
})})`
);
return true;
@@ -235,16 +235,16 @@ class API {
public removeFeature({ data }, window) {
this.currentPlugin = {
...this.currentPlugin,
features: this.currentPlugin.features.filter(feature => {
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
currentPlugin: this.currentPlugin,
})})`
);
return true;
@@ -255,14 +255,14 @@ class API {
if (!code || !runnerInstance.getView()) return;
if (modifiers.length > 0) {
runnerInstance.getView().webContents.sendInputEvent({
type: "keyDown",
type: 'keyDown',
modifiers,
keyCode: code
keyCode: code,
});
} else {
runnerInstance.getView().webContents.sendInputEvent({
type: "keyDown",
keyCode: code
type: 'keyDown',
keyCode: code,
});
}
}
@@ -273,11 +273,11 @@ class API {
window.setBrowserView(null);
window.webContents
.executeJavaScript(`window.getMainInputInfo()`)
.then(res => {
.then((res) => {
detachInstance.init(
{
...this.currentPlugin,
subInput: res
subInput: res,
},
window.getBounds(),
view
@@ -293,7 +293,7 @@ class API {
}
public getLocalId() {
return encodeURIComponent(app.getPath("home"));
return encodeURIComponent(app.getPath('home'));
}
public shellShowItemInFolder({ data }) {

View File

@@ -38,7 +38,6 @@ class App {
this.onQuit();
}
}
beforeReady() {
// 系统托盘
if (commonConst.macOS()) {
@@ -55,7 +54,6 @@ class App {
createWindow() {
this.windowCreator.init();
}
onReady() {
const readyFunction = () => {
this.createWindow();

View File

@@ -36,13 +36,13 @@
</template>
<script setup lang="ts">
import { watch, ref, nextTick, toRaw } from "vue";
import { ipcRenderer, remote } from "electron";
import Result from "./components/result.vue";
import Search from "./components/search.vue";
import getWindowHeight from "../common/utils/getWindowHeight";
import createPluginManager from "./plugins-manager";
import commonConst from "@/common/utils/commonConst";
import { watch, ref, nextTick, toRaw } from 'vue';
import { ipcRenderer, remote } from 'electron';
import Result from './components/result.vue';
import Search from './components/search.vue';
import getWindowHeight from '../common/utils/getWindowHeight';
import createPluginManager from './plugins-manager';
import commonConst from '@/common/utils/commonConst';
const {
initPlugins,
@@ -59,35 +59,35 @@ const {
clipboardFile,
setSearchValue,
clearClipboardFile,
readClipboardContent
readClipboardContent,
} = createPluginManager();
initPlugins();
const currentSelect = ref(0);
const menuPluginInfo = ref({});
const menuPluginInfo: any = ref({});
getPluginInfo({
pluginName: "feature",
pluginName: 'feature',
// eslint-disable-next-line no-undef
pluginPath: `${__static}/feature/package.json`
}).then(res => {
pluginPath: `${__static}/feature/package.json`,
}).then((res) => {
menuPluginInfo.value = res;
remote.getGlobal("LOCAL_PLUGINS").addPlugin(res);
remote.getGlobal('LOCAL_PLUGINS').addPlugin(res);
});
watch([options], () => {
currentSelect.value = 0;
if (currentPlugin.value.name) return;
nextTick(() => {
ipcRenderer.sendSync("msg-trigger", {
type: "setExpendHeight",
data: getWindowHeight(options.value)
ipcRenderer.sendSync('msg-trigger', {
type: 'setExpendHeight',
data: getWindowHeight(options.value),
});
});
});
const changeIndex = index => {
const changeIndex = (index) => {
if (!options.value.length) return;
if (
currentSelect.value + index > options.value.length - 1 ||
@@ -101,12 +101,12 @@ const openMenu = (ext) => {
openPlugin({
...toRaw(menuPluginInfo.value),
feature: menuPluginInfo.value.features[0],
cmd: "插件市场",
ext
cmd: '插件市场',
ext,
});
};
window.rubick.openMenu = openMenu
window.rubick.openMenu = openMenu;
const choosePlugin = () => {
const currentChoose = options.value[currentSelect.value];
@@ -114,12 +114,12 @@ const choosePlugin = () => {
};
const clearSearchValue = () => {
setSearchValue("");
setSearchValue('');
};
</script>
<style lang="less">
@import "./assets/var.less";
@import './assets/var.less';
.drag-bar {
-webkit-app-region: drag;
width: 100%;
@@ -129,6 +129,7 @@ const clearSearchValue = () => {
top: 0;
left: 0;
}
#components-layout {
height: 100vh;
overflow: hidden;
@@ -137,6 +138,7 @@ const clearSearchValue = () => {
width: 0;
}
}
.drag {
-webkit-app-region: drag;
}

View File

@@ -29,8 +29,9 @@
</template>
<script lang="ts" setup>
import BScroll from "@better-scroll/core";
import { defineProps, onMounted, ref } from "vue";
import BScroll from '@better-scroll/core';
import { defineProps, onMounted, ref } from 'vue';
const scrollDom = ref(null);
onMounted(() => {
@@ -40,32 +41,32 @@ onMounted(() => {
const props = defineProps({
searchValue: {
type: [String, Number],
default: ""
default: '',
},
options: {
type: Array,
default: (() => [])()
default: (() => [])(),
},
currentSelect: {
type: Number,
default: 0
default: 0,
},
currentPlugin: {},
clipboardFile: (() => [])()
clipboardFile: (() => [])(),
});
const renderTitle = title => {
if (typeof title !== "string") return;
const renderTitle = (title) => {
if (typeof title !== 'string') return;
if (!props.searchValue) return title;
const result = title.toLowerCase().split(props.searchValue.toLowerCase());
if (result && result.length > 1) {
return `<div>${result[0]}<span style="color: red">${props.searchValue}</span>${result[1]}</div>`;
return `<div>${result[0]}<span style='color: red'>${props.searchValue}</span>${result[1]}</div>`;
} else {
return `<div>${result[0]}</div>`;
}
};
const renderDesc = desc => {
const renderDesc = (desc) => {
if (desc.length > 80) {
return `${desc.substr(0, 63)}...${desc.substr(
desc.length - 14,
@@ -75,7 +76,7 @@ const renderDesc = desc => {
return desc;
};
const sort = options => {
const sort = (options) => {
for (let i = 0; i < options.length; i++) {
for (let j = i + 1; j < options.length; j++) {
if (options[j].zIndex > options[i].zIndex) {
@@ -96,7 +97,7 @@ const sort = options => {
left: 0;
width: 100%;
z-index: 99;
max-height: calc(~"100vh - 64px");
max-height: calc(~'100vh - 64px');
overflow: auto;
background: var(--color-body-bg);
.op-item {

View File

@@ -51,10 +51,11 @@
</template>
<script setup lang="ts">
import { defineProps, defineEmits, ref, computed } from "vue";
import { ipcRenderer, remote } from "electron";
import { LoadingOutlined, MoreOutlined } from "@ant-design/icons-vue";
const opConfig = remote.getGlobal("OP_CONFIG");
import { defineProps, defineEmits, ref } from 'vue';
import { ipcRenderer, remote } from 'electron';
import { LoadingOutlined, MoreOutlined } from '@ant-design/icons-vue';
const opConfig = remote.getGlobal('OP_CONFIG');
const { Menu } = remote;
const config = ref(opConfig.get());
@@ -62,63 +63,63 @@ const config = ref(opConfig.get());
const props: any = defineProps({
searchValue: {
type: [String, Number],
default: ""
default: '',
},
placeholder: {
type: String,
default: ""
default: '',
},
currentPlugin: {},
pluginLoading: Boolean,
clipboardFile: (() => [])()
clipboardFile: (() => [])(),
});
const changeValue = e => {
if (props.currentPlugin.name === "rubick-system-feature") return;
if (props.currentPlugin.name === 'rubick-system-feature') return;
targetSearch({ value: e.target.value });
emit("onSearch", e);
emit('onSearch', e);
};
const emit = defineEmits([
"onSearch",
"changeCurrent",
"openMenu",
"changeSelect",
"choosePlugin",
"focus",
"clearSearchValue",
"readClipboardContent"
'onSearch',
'changeCurrent',
'openMenu',
'changeSelect',
'choosePlugin',
'focus',
'clearSearchValue',
'readClipboardContent',
]);
const keydownEvent = (e, key: string) => {
const { ctrlKey, shiftKey, altKey, metaKey } = e;
const modifiers: Array<string> = [];
ctrlKey && modifiers.push("control");
shiftKey && modifiers.push("shift");
altKey && modifiers.push("alt");
metaKey && modifiers.push("meta");
ipcRenderer.send("msg-trigger", {
type: "sendPluginSomeKeyDownEvent",
ctrlKey && modifiers.push('control');
shiftKey && modifiers.push('shift');
altKey && modifiers.push('alt');
metaKey && modifiers.push('meta');
ipcRenderer.send('msg-trigger', {
type: 'sendPluginSomeKeyDownEvent',
data: {
keyCode: e.code,
modifiers
}
modifiers,
},
});
const runPluginDisable = e.target.value === "" || props.currentPlugin.name;
const runPluginDisable = e.target.value === '' || props.currentPlugin.name;
switch (key) {
case "up":
emit("changeCurrent", -1);
case 'up':
emit('changeCurrent', -1);
break;
case "down":
emit("changeCurrent", 1);
case 'down':
emit('changeCurrent', 1);
break;
case "enter":
case 'enter':
if (runPluginDisable) return;
emit("choosePlugin");
emit('choosePlugin');
break;
case "space":
case 'space':
if (runPluginDisable || !opConfig.get().perf.common.space) return;
emit("choosePlugin");
emit('choosePlugin');
break;
default:
break;
@@ -128,63 +129,63 @@ const keydownEvent = (e, key: string) => {
const checkNeedInit = e => {
const { ctrlKey, metaKey } = e;
if (e.target.value === "" && e.keyCode === 8) {
if (e.target.value === '' && e.keyCode === 8) {
closeTag();
}
// 手动粘贴
if ((ctrlKey || metaKey) && e.key === "v") {
emit("readClipboardContent");
if ((ctrlKey || metaKey) && e.key === 'v') {
emit('readClipboardContent');
}
};
const targetSearch = ({ value }) => {
if (props.currentPlugin.name) {
return ipcRenderer.sendSync("msg-trigger", {
type: "sendSubInputChangeEvent",
data: { text: value }
return ipcRenderer.sendSync('msg-trigger', {
type: 'sendSubInputChangeEvent',
data: { text: value },
});
}
};
const closeTag = () => {
emit("changeSelect", {});
emit("clearClipbord");
ipcRenderer.send("msg-trigger", {
type: "removePlugin"
emit('changeSelect', {});
emit('clearClipbord');
ipcRenderer.send('msg-trigger', {
type: 'removePlugin',
});
};
const showSeparate = () => {
let pluginMenu: any = [
{
label: config.value.perf.common.hideOnBlur ? "钉住" : "自动隐藏",
click: changeHideOnBlur
}
label: config.value.perf.common.hideOnBlur ? '钉住' : '自动隐藏',
click: changeHideOnBlur,
},
];
if (props.currentPlugin && props.currentPlugin.logo) {
pluginMenu = pluginMenu.concat([
{
label: "开发者工具",
label: '开发者工具',
click: () => {
ipcRenderer.send("msg-trigger", { type: "openPluginDevTools" });
ipcRenderer.send('msg-trigger', { type: 'openPluginDevTools' });
// todo
}
},
},
{
label: "当前插件信息",
label: '当前插件信息',
submenu: [
{
label: "简介"
label: '简介',
},
{
label: "功能"
}
]
label: '功能',
},
],
},
{
label: "分离窗口",
click: newWindow
}
label: '分离窗口',
click: newWindow,
},
]);
}
let menu = Menu.buildFromTemplate(pluginMenu);
@@ -201,13 +202,13 @@ const changeHideOnBlur = () => {
const getIcon = () => {
if (props.clipboardFile[0].dataUrl) return props.clipboardFile[0].dataUrl;
return props.clipboardFile[0].isFile
? require("../assets/file.png")
: require("../assets/folder.png");
? require('../assets/file.png')
: require('../assets/folder.png');
};
const newWindow = () => {
ipcRenderer.send("msg-trigger", {
type: "detachPlugin"
ipcRenderer.send('msg-trigger', {
type: 'detachPlugin',
});
// todo
};
@@ -218,7 +219,7 @@ window.rubick.hooks.onShow = () => {
};
window.rubick.hooks.onHide = () => {
emit("clearSearchValue");
emit('clearSearchValue');
};
</script>
@@ -238,6 +239,7 @@ window.rubick.hooks.onHide = () => {
white-space: nowrap;
max-width: 200px;
}
.select-tag {
white-space: pre;
user-select: none;
@@ -252,6 +254,7 @@ window.rubick.hooks.onHide = () => {
margin-right: 1px;
padding: 0 10px;
}
.main-input {
height: 60px !important;
box-sizing: border-box;
@@ -270,6 +273,7 @@ window.rubick.hooks.onHide = () => {
color: var(--color-text-primary);
}
}
.rubick-logo,
.icon-tool {
width: 40px;

View File

@@ -1,6 +1,6 @@
import { createApp } from "vue";
import { Button, List, Spin, Input, Avatar, Tag } from "ant-design-vue";
import App from "./App.vue";
import { createApp } from 'vue';
import { Button, List, Spin, Input, Avatar, Tag } from 'ant-design-vue';
import App from './App.vue';
createApp(App)
.use(Button)
@@ -9,4 +9,4 @@ createApp(App)
.use(Input)
.use(Avatar)
.use(Tag)
.mount("#app");
.mount('#app');

View File

@@ -1,13 +1,13 @@
import getCopyFiles from "@/common/utils/getCopyFiles";
import { clipboard, nativeImage, remote, ipcRenderer } from "electron";
import path from "path";
import pluginClickEvent from "./pluginClickEvent";
import { ref } from "vue";
import getCopyFiles from '@/common/utils/getCopyFiles';
import { clipboard, nativeImage, remote, ipcRenderer } from 'electron';
import path from 'path';
import pluginClickEvent from './pluginClickEvent';
import { ref } from 'vue';
export default ({ currentPlugin, optionsRef, openPlugin, setOptionsRef }) => {
const clipboardFile: any = ref([]);
const searchFocus = () => {
const config = remote.getGlobal("OP_CONFIG").get();
const config = remote.getGlobal('OP_CONFIG').get();
// 未开启自动粘贴
if (!config.perf.common.autoPast) return;
@@ -15,18 +15,18 @@ export default ({ currentPlugin, optionsRef, openPlugin, setOptionsRef }) => {
const fileList = getCopyFiles();
// 拷贝的是文件
if (fileList) {
window.setSubInputValue({ value: "" });
window.setSubInputValue({ value: '' });
clipboardFile.value = fileList;
const localPlugins = remote.getGlobal("LOCAL_PLUGINS").getLocalPlugins();
const localPlugins = remote.getGlobal('LOCAL_PLUGINS').getLocalPlugins();
const options: any = [
{
name: "复制路径",
value: "plugin",
icon: require("../assets/link.png"),
desc: "复制路径到剪切板",
name: '复制路径',
value: 'plugin',
icon: require('../assets/link.png'),
desc: '复制路径到剪切板',
click: () => {
clipboard.writeText(fileList.map((file) => file.path).join(","));
ipcRenderer.send("msg-trigger", { type: "hideMainWindow" });
clipboard.writeText(fileList.map((file) => file.path).join(','));
ipcRenderer.send('msg-trigger', { type: 'hideMainWindow' });
},
},
];
@@ -50,13 +50,13 @@ export default ({ currentPlugin, optionsRef, openPlugin, setOptionsRef }) => {
fe.cmds.forEach((cmd) => {
const regImg = /\.(png|jpg|gif|jpeg|webp)$/;
if (
cmd.type === "img" &&
cmd.type === 'img' &&
regImg.test(ext) &&
fileList.length === 1
) {
options.push({
name: cmd.label,
value: "plugin",
value: 'plugin',
icon: plugin.logo,
desc: fe.explain,
type: plugin.pluginType,
@@ -67,7 +67,7 @@ export default ({ currentPlugin, optionsRef, openPlugin, setOptionsRef }) => {
cmd,
ext: {
code: fe.code,
type: cmd.type || "text",
type: cmd.type || 'text',
payload: nativeImage
.createFromPath(fileList[0].path)
.toDataURL(),
@@ -81,11 +81,11 @@ export default ({ currentPlugin, optionsRef, openPlugin, setOptionsRef }) => {
// 如果是文件,且符合文件正则类型
if (
fileList.length > 1 ||
(cmd.type === "file" && new RegExp(cmd.match).test(ext))
(cmd.type === 'file' && new RegExp(cmd.match).test(ext))
) {
options.push({
name: cmd,
value: "plugin",
value: 'plugin',
icon: plugin.logo,
desc: fe.explain,
type: plugin.pluginType,
@@ -96,7 +96,7 @@ export default ({ currentPlugin, optionsRef, openPlugin, setOptionsRef }) => {
cmd,
ext: {
code: fe.code,
type: cmd.type || "text",
type: cmd.type || 'text',
payload: fileList,
},
openPlugin,
@@ -115,7 +115,7 @@ export default ({ currentPlugin, optionsRef, openPlugin, setOptionsRef }) => {
}
const clipboardType = clipboard.availableFormats();
if (!clipboardType.length) return;
if ("text/plain" === clipboardType[0]) {
if ('text/plain' === clipboardType[0]) {
const contentText = clipboard.readText();
if (contentText.trim()) {
clearClipboardFile();
@@ -134,7 +134,7 @@ export default ({ currentPlugin, optionsRef, openPlugin, setOptionsRef }) => {
// read image
const img = clipboard.readImage();
const dataUrl = img.toDataURL();
if (!dataUrl.replace("data:image/png;base64,", "")) return;
if (!dataUrl.replace('data:image/png;base64,', '')) return;
clipboardFile.value = [
{
isFile: true,
@@ -143,7 +143,7 @@ export default ({ currentPlugin, optionsRef, openPlugin, setOptionsRef }) => {
dataUrl,
},
];
const localPlugins = remote.getGlobal("LOCAL_PLUGINS").getLocalPlugins();
const localPlugins = remote.getGlobal('LOCAL_PLUGINS').getLocalPlugins();
const options: any = [];
// 再正则插件
localPlugins.forEach((plugin) => {
@@ -152,10 +152,10 @@ export default ({ currentPlugin, optionsRef, openPlugin, setOptionsRef }) => {
if (!feature) return;
feature.forEach((fe) => {
fe.cmds.forEach((cmd) => {
if (cmd.type === "img") {
if (cmd.type === 'img') {
options.push({
name: cmd.label,
value: "plugin",
value: 'plugin',
icon: plugin.logo,
desc: fe.explain,
type: plugin.pluginType,
@@ -166,7 +166,7 @@ export default ({ currentPlugin, optionsRef, openPlugin, setOptionsRef }) => {
cmd,
ext: {
code: fe.code,
type: cmd.type || "text",
type: cmd.type || 'text',
payload: dataUrl,
},
openPlugin,

View File

@@ -1,13 +1,13 @@
import { reactive, toRefs, ref } from "vue";
import { nativeImage, remote, ipcRenderer } from "electron";
import appSearch from "@/core/app-search";
import { PluginHandler } from "@/core";
import path from "path";
import commonConst from "@/common/utils/commonConst";
import { execSync } from "child_process";
import searchManager from "./search";
import optionsManager from "./options";
import { PLUGIN_INSTALL_DIR as baseDir } from "@/common/constans/renderer";
import { reactive, toRefs, ref } from 'vue';
import { nativeImage, remote, ipcRenderer } from 'electron';
import appSearch from '@/core/app-search';
import { PluginHandler } from '@/core';
import path from 'path';
import commonConst from '@/common/utils/commonConst';
import { execSync } from 'child_process';
import searchManager from './search';
import optionsManager from './options';
import { PLUGIN_INSTALL_DIR as baseDir } from '@/common/constans/renderer';
const createPluginManager = (): any => {
const pluginInstance = new PluginHandler({
@@ -34,27 +34,27 @@ const createPluginManager = (): any => {
};
const openPlugin = (plugin) => {
if (plugin.pluginType === "ui" || plugin.pluginType === "system") {
if (plugin.pluginType === 'ui' || plugin.pluginType === 'system') {
if (state.currentPlugin && state.currentPlugin.name === plugin.name) {
return;
}
loadPlugin(plugin);
ipcRenderer.sendSync("msg-trigger", {
type: "openPlugin",
ipcRenderer.sendSync('msg-trigger', {
type: 'openPlugin',
data: JSON.parse(
JSON.stringify({
...plugin,
ext: plugin.ext || {
code: plugin.feature.code,
type: plugin.cmd.type || "text",
type: plugin.cmd.type || 'text',
payload: null,
},
})
),
});
setSearchValue("");
setSearchValue('');
}
if (plugin.pluginType === "app") {
if (plugin.pluginType === 'app') {
execSync(plugin.action);
}
};
@@ -83,8 +83,8 @@ const createPluginManager = (): any => {
...pluginInfo,
icon: pluginInfo.logo,
indexPath: commonConst.dev()
? "http://localhost:8081/#/"
: `file://${path.join(pluginPath, "../", pluginInfo.main)}`,
? 'http://localhost:8081/#/'
: `file://${path.join(pluginPath, '../', pluginInfo.main)}`,
};
};
@@ -104,18 +104,18 @@ const createPluginManager = (): any => {
window.updatePlugin = ({ currentPlugin }: any) => {
state.currentPlugin = currentPlugin;
remote.getGlobal("LOCAL_PLUGINS").updatePlugin(currentPlugin);
remote.getGlobal('LOCAL_PLUGINS').updatePlugin(currentPlugin);
};
window.setCurrentPlugin = ({ currentPlugin }) => {
state.currentPlugin = currentPlugin;
setSearchValue("");
setSearchValue('');
};
window.initRubick = () => {
state.currentPlugin = {};
setSearchValue("");
window.setSubInput({ placeholder: "" });
setSearchValue('');
window.setSubInput({ placeholder: '' });
};
window.pluginLoaded = () => {

View File

@@ -1,21 +1,21 @@
import { ref, watch } from "vue";
import throttle from "lodash.throttle";
import { remote, ipcRenderer } from "electron";
import pluginClickEvent from "./pluginClickEvent";
import useFocus from "./clipboardWatch";
import { ref, watch } from 'vue';
import throttle from 'lodash.throttle';
import { remote, ipcRenderer } from 'electron';
import pluginClickEvent from './pluginClickEvent';
import useFocus from './clipboardWatch';
function formatReg(regStr) {
const flags = regStr.replace(/.*\/([gimy]*)$/, "$1");
const pattern = flags.replace(new RegExp("^/(.*?)/" + flags + "$"), "$1");
const flags = regStr.replace(/.*\/([gimy]*)$/, '$1');
const pattern = flags.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1');
return new RegExp(pattern, flags);
}
function searchKeyValues(lists, value, strict = false) {
return lists.filter((item) => {
if (typeof item === "string") {
if (typeof item === 'string') {
return item.toLowerCase().indexOf(value.toLowerCase()) >= 0;
}
if (item.type === "regex" && !strict) {
if (item.type === 'regex' && !strict) {
return formatReg(item.match).test(value);
}
return false;
@@ -31,13 +31,13 @@ const optionsManager = ({
const optionsRef = ref([]);
// 全局快捷键
ipcRenderer.on("global-short-key", (e, msg) => {
ipcRenderer.on('global-short-key', (e, msg) => {
const options = getOptionsFromSearchValue(msg, true);
options[0].click();
});
const getOptionsFromSearchValue = (value, strict = false) => {
const localPlugins = remote.getGlobal("LOCAL_PLUGINS").getLocalPlugins();
const localPlugins = remote.getGlobal('LOCAL_PLUGINS').getLocalPlugins();
let options: any = [];
// todo 先搜索 plugin
localPlugins.forEach((plugin) => {
@@ -50,7 +50,7 @@ const optionsManager = ({
...options,
...cmds.map((cmd) => ({
name: cmd.label || cmd,
value: "plugin",
value: 'plugin',
icon: plugin.logo,
desc: fe.explain,
type: plugin.pluginType,
@@ -63,7 +63,7 @@ const optionsManager = ({
ext: cmd.type
? {
code: fe.code,
type: cmd.type || "text",
type: cmd.type || 'text',
payload: searchValue.value,
}
: null,

View File

@@ -1,13 +1,13 @@
import { PLUGIN_INSTALL_DIR as baseDir } from "@/common/constans/renderer";
import path from "path";
import { toRaw } from "vue";
import commonConst from "@/common/utils/commonConst";
import { PLUGIN_INSTALL_DIR as baseDir } from '@/common/constans/renderer';
import path from 'path';
import { toRaw } from 'vue';
import commonConst from '@/common/utils/commonConst';
export default function pluginClickEvent({ plugin, fe, cmd, ext, openPlugin }) {
const pluginPath = path.resolve(baseDir, "node_modules", plugin.name);
const pluginPath = path.resolve(baseDir, 'node_modules', plugin.name);
const pluginDist = {
...toRaw(plugin),
indexPath: `file://${path.join(pluginPath, "./", plugin.main || "")}`,
indexPath: `file://${path.join(pluginPath, './', plugin.main || '')}`,
cmd: cmd.label || cmd,
feature: fe,
ext,
@@ -15,13 +15,13 @@ export default function pluginClickEvent({ plugin, fe, cmd, ext, openPlugin }) {
// 模板文件
if (!plugin.main) {
pluginDist.tplPath = commonConst.dev()
? "http://localhost:8082/#/"
? 'http://localhost:8082/#/'
: `file://${__static}/tpl/index.html`;
}
// 插件市场
if (plugin.name === "rubick-system-feature") {
if (plugin.name === 'rubick-system-feature') {
pluginDist.indexPath = commonConst.dev()
? "http://localhost:8081/#/"
? 'http://localhost:8081/#/'
: `file://${__static}/feature/index.html`;
}
openPlugin(pluginDist);

View File

@@ -1,10 +1,9 @@
import { reactive, toRefs } from "vue";
import { ipcRenderer, remote } from "electron";
import { reactive, toRefs } from 'vue';
const searchManager = () => {
const state = reactive({
searchValue: "",
placeholder: "",
searchValue: '',
placeholder: '',
});
// search Input operation
@@ -21,7 +20,7 @@ const searchManager = () => {
state.placeholder = placeholder;
};
window.removeSubInput = () => {
state.placeholder = "";
state.placeholder = '';
};
window.setSubInputValue = ({ value }: { value: string }) => {
state.searchValue = value;

View File

@@ -1,17 +1,17 @@
/* eslint-disable */
declare module "*.vue" {
import type { DefineComponent } from "vue";
declare module '*.vue' {
import type { DefineComponent } from 'vue';
const component: DefineComponent<{}, {}, any>;
export default component;
}
declare module "main" {
declare module 'main' {
export function main(): any;
}
declare const __static: string;
declare module "lodash.throttle";
declare module 'lodash.throttle';
interface Window {
rubick: any;