♻️ 代码重构

This commit is contained in:
muwoo 2021-12-06 18:23:34 +08:00
parent cd41f0561c
commit 1353c440aa
29 changed files with 295 additions and 13562 deletions

View File

@ -1 +1,13 @@
console.log("hello"); const {remote} = require("electron");
window.market = {
getLocalPlugins() {
return remote.getGlobal("LOCAL_PLUGINS").getLocalPlugins();
},
downloadPlugin(plugin) {
return remote.getGlobal("LOCAL_PLUGINS").downloadPlugin(plugin);
},
deletePlugin(plugin) {
return remote.getGlobal("LOCAL_PLUGINS").deletePlugin(plugin);
},
}

View File

@ -51,6 +51,10 @@ const changeMenu = (key: any) => {
const store = useStore(); const store = useStore();
const init = () => store.dispatch("init"); const init = () => store.dispatch("init");
init(); init();
(window as any).rubick.onPluginEnter((res) => {
console.log(res);
})
</script> </script>
<style lang="less"> <style lang="less">
* { * {

View File

@ -27,7 +27,7 @@ export default createStore({
actions: { actions: {
async init({ commit }) { async init({ commit }) {
const totalPlugins = await request.getTotalPlugins(); const totalPlugins = await request.getTotalPlugins();
const localPlugins = (window as any).rubick.getLocalPlugins(); const localPlugins = (window as any).market.getLocalPlugins();
totalPlugins.forEach( totalPlugins.forEach(
(origin: { isdwonload?: any; name?: any; isloading: boolean }) => { (origin: { isdwonload?: any; name?: any; isloading: boolean }) => {
@ -63,7 +63,7 @@ export default createStore({
} }
} }
); );
const localPlugins = (window as any).rubick.getLocalPlugins(); const localPlugins = (window as any).market.getLocalPlugins();
commit("commonUpdate", { commit("commonUpdate", {
totalPlugins, totalPlugins,
@ -71,7 +71,7 @@ export default createStore({
}); });
}, },
updateLocalPlugin({ commit }) { updateLocalPlugin({ commit }) {
const localPlugins = (window as any).rubick.getLocalPlugins(); const localPlugins = (window as any).market.getLocalPlugins();
commit("commonUpdate", { commit("commonUpdate", {
localPlugins, localPlugins,
}); });

View File

@ -83,7 +83,7 @@ const readme = computed(() => {
}); });
const deletePlugin = async (plugin) => { const deletePlugin = async (plugin) => {
await window.rubick.deletePlugin(plugin); await window.market.deletePlugin(plugin);
updateLocalPlugin(); updateLocalPlugin();
}; };
</script> </script>

View File

@ -15,8 +15,17 @@
<img @click="jumpTo(banner.link)" width="100%" :src="banner.src" /> <img @click="jumpTo(banner.link)" width="100%" :src="banner.src" />
</div> </div>
</a-carousel> </a-carousel>
<PluginList @downloadSuccess="downloadSuccess" title="推荐" :list="recommend || []" /> <PluginList
<PluginList title="最近更新" :list="newList || []" /> v-if="recommend && !!recommend.length"
@downloadSuccess="downloadSuccess"
title="推荐"
:list="recommend"
/>
<PluginList
v-if="newList && !!newList.length"
title="最近更新"
:list="newList"
/>
</div> </div>
</template> </template>
@ -25,7 +34,7 @@ import {
LeftCircleOutlined, LeftCircleOutlined,
RightCircleOutlined, RightCircleOutlined,
} from "@ant-design/icons-vue"; } from "@ant-design/icons-vue";
import { ref, computed } from "vue"; import { ref, computed, onBeforeMount } from "vue";
import request from "../../../assets/request/index"; import request from "../../../assets/request/index";
import PluginList from "./plugin-list.vue"; import PluginList from "./plugin-list.vue";
@ -35,8 +44,9 @@ const totalPlugins = computed(() => store.state.totalPlugins);
const data = ref([]); const data = ref([]);
request.getFinderDetail().then(res => { onBeforeMount(async () => {
data.value = res; console.log(12312);
data.value = await request.getFinderDetail();
}); });
const recommend = computed(() => { const recommend = computed(() => {

View File

@ -73,7 +73,7 @@ import {
ArrowLeftOutlined, ArrowLeftOutlined,
} from "@ant-design/icons-vue"; } from "@ant-design/icons-vue";
import { computed, defineProps, ref } from "vue"; import { defineProps, ref } from "vue";
import { useStore } from "vuex"; import { useStore } from "vuex";
const store = useStore(); const store = useStore();
@ -91,7 +91,7 @@ defineProps({
const downloadPlugin = async (plugin) => { const downloadPlugin = async (plugin) => {
startDownload(plugin.name); startDownload(plugin.name);
await window.rubick.downloadPlugin(plugin); await window.market.downloadPlugin(plugin);
successDownload(plugin.name); successDownload(plugin.name);
}; };

View File

@ -1,13 +1,46 @@
const {remote} = require("electron"); const {ipcRenderer} = require("electron");
console.log(remote)
const ipcSendSync = (type, data) => {
const returnValue = ipcRenderer.sendSync("msg-trigger", {
type,
data,
});
if (returnValue instanceof Error) throw returnValue;
return returnValue;
};
window.rubick = { window.rubick = {
getLocalPlugins() { hooks: {},
return remote.getGlobal("LOCAL_PLUGINS").getLocalPlugins(); // 事件
onPluginEnter(cb) {
console.log(window.rubick.hooks)
typeof cb === "function" && (window.rubick.hooks.onPluginEnter = cb);
}, },
downloadPlugin(plugin) { onPluginReady(cb) {
return remote.getGlobal("LOCAL_PLUGINS").downloadPlugin(plugin); typeof cb === "function" && (window.rubick.hooks.onPluginReady = cb);
}, },
deletePlugin(plugin) { onPluginOut(cb) {
return remote.getGlobal("LOCAL_PLUGINS").deletePlugin(plugin); typeof cb === "function" && (window.rubick.hooks.onPluginOut = cb);
},
// 窗口交互
hideMainWindow() {
ipcSendSync("hideMainWindow");
},
showMainWindow() {
ipcSendSync("showMainWindow");
},
showOpenDialog(options) {
ipcSendSync("showOpenDialog", options);
},
setExpendHeight(height) {
ipcSendSync("setExpendHeight", height);
},
setSubInput(onChange, placeholder = "", isFocus) {
typeof cb === "function" && (window.rubick.hooks.onSubInputChange = onChange);
ipcSendSync("setSubInput", {
placeholder,
isFocus,
});
}, },
}; };

23
runner/.gitignore vendored
View File

@ -1,23 +0,0 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@ -1,24 +0,0 @@
# runner
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

View File

@ -1,3 +0,0 @@
module.exports = {
presets: ["@vue/cli-plugin-babel/preset"],
};

13200
runner/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,56 +0,0 @@
{
"name": "runner",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.6.5",
"vue": "^3.0.0",
"vue-router": "^4.0.0-0",
"vuex": "^4.0.0-0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^4.18.0",
"@typescript-eslint/parser": "^4.18.0",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-typescript": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0",
"@vue/eslint-config-prettier": "^6.0.0",
"@vue/eslint-config-typescript": "^7.0.0",
"eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-vue": "^7.0.0",
"prettier": "^2.2.1",
"typescript": "~4.1.5"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended",
"@vue/typescript/recommended",
"@vue/prettier",
"@vue/prettier/@typescript-eslint"
],
"parserOptions": {
"ecmaVersion": 2020
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -1,17 +0,0 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -1,41 +0,0 @@
<template>
<webview
v-if="preload"
id="webview"
:src="`File://${pluginInfo.indexPath}`"
:preload="preload"
/>
</template>
<script setup >
import { reactive, toRefs, onMounted } from "vue";
const state = reactive({
pluginInfo: {},
});
window.setPluginInfo = (pluginInfo) => {
console.log(pluginInfo);
try {
state.pluginInfo = pluginInfo;
} catch (e) {
//
}
};
const { pluginInfo, preload } = toRefs(state);
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#webview {
width: 100%;
height: 100vh;
}
</style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -1,4 +0,0 @@
import { createApp } from "vue";
import App from "./App.vue";
createApp(App).mount("#app");

View File

@ -1,8 +0,0 @@
/* eslint-disable */
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
declare const __static: string

View File

@ -1,39 +0,0 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}

View File

@ -1,6 +0,0 @@
const path = require("path");
module.exports = {
outputDir: path.join(__dirname, "../public/runner"),
publicPath: process.env.NODE_ENV === "production" ? "" : "/",
};

View File

@ -13,7 +13,7 @@ export default () => {
const createView = (plugin, window: BrowserWindow) => { const createView = (plugin, window: BrowserWindow) => {
const preload = commonConst.dev() const preload = commonConst.dev()
? `http://localhost:8080/preload.js` ? path.resolve(__static, `../feature/public/preload.js`)
: path.resolve(plugin.indexPath, `../`, plugin.preload); : path.resolve(plugin.indexPath, `../`, plugin.preload);
const ses = session.fromPartition("<" + plugin.name + ">"); const ses = session.fromPartition("<" + plugin.name + ">");
@ -38,6 +38,8 @@ export default () => {
view.setAutoResize({ width: true }); view.setAutoResize({ width: true });
window.setSize(800, 660); window.setSize(800, 660);
view.webContents.openDevTools(); view.webContents.openDevTools();
executeHooks(plugin.ext, "PluginEnter");
executeHooks(plugin.ext, "PluginReady");
}); });
}; };
@ -45,11 +47,22 @@ export default () => {
if (!view) return; if (!view) return;
window.removeBrowserView(view); window.removeBrowserView(view);
window.setSize(800, 60); window.setSize(800, 60);
executeHooks("PluginOut", null);
view = undefined; view = undefined;
}; };
const getView = () => view; const getView = () => view;
const executeHooks = (hook, data) => {
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) : ""});
} catch(e) {}
}
`;
view.webContents.executeJavaScript(evalJs);
};
return { return {
init, init,
getView, getView,

View File

@ -1,12 +1,9 @@
import { BrowserWindow, ipcMain } from "electron"; import { BrowserWindow, ipcMain, dialog } from "electron";
import { runner } from "../browsers"; import { runner } from "../browsers";
const runnerInstance = runner(); const runnerInstance = runner();
const API: any = { const API: any = {
setExpendHeight({ height }: { height: number }, win: BrowserWindow): void {
win.setSize(800, height || 60);
},
openPlugin({ plugin }, window) { openPlugin({ plugin }, window) {
runnerInstance.removeView(window); runnerInstance.removeView(window);
runnerInstance.init(plugin, window); runnerInstance.init(plugin, window);
@ -14,6 +11,22 @@ const API: any = {
removePlugin(e, window) { removePlugin(e, window) {
runnerInstance.removeView(window); runnerInstance.removeView(window);
}, },
hideMainWindow(arg, window) {
window.hide();
},
showMainWindow(arg, window) {
window.show();
},
showOpenDialog({ data }, window) {
dialog.showOpenDialogSync(window, data);
},
setExpendHeight({ data: height }, window: BrowserWindow) {
const targetHeight = height;
window.setSize(window.getSize()[0], targetHeight);
},
setSubInput() {
},
}; };
export default (mainWindow: BrowserWindow) => { export default (mainWindow: BrowserWindow) => {

View File

@ -7,9 +7,15 @@
@onSearch="onSearch" @onSearch="onSearch"
@openMenu="openMenu" @openMenu="openMenu"
@changeSelect="changeSelect" @changeSelect="changeSelect"
:searchValue="searchValue"
/> />
</div> </div>
<Result :searchValue="searchValue" :currentSelect="currentSelect" :options="options" /> <Result
:currentPlugin="currentPlugin"
:searchValue="searchValue"
:currentSelect="currentSelect"
:options="options"
/>
</div> </div>
</template> </template>
@ -40,7 +46,7 @@ const menuPluginInfo = ref({});
getPluginInfo({ getPluginInfo({
pluginName: "feature", pluginName: "feature",
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
pluginPath: `${__static}/feature/plugin.json`, pluginPath: `${__static}/feature/package.json`,
}).then((res) => { }).then((res) => {
menuPluginInfo.value = res; menuPluginInfo.value = res;
}); });
@ -50,7 +56,7 @@ watch([searchValue], () => {
nextTick(() => { nextTick(() => {
ipcRenderer.sendSync("msg-trigger", { ipcRenderer.sendSync("msg-trigger", {
type: "setExpendHeight", type: "setExpendHeight",
height: getWindowHeight(searchValue.value ? options.value : []), data: getWindowHeight(searchValue.value ? options.value : []),
}); });
}); });
}); });
@ -68,6 +74,7 @@ const changeIndex = (index) => {
const openMenu = () => { const openMenu = () => {
openPlugin({ openPlugin({
...toRaw(menuPluginInfo.value), ...toRaw(menuPluginInfo.value),
feature: menuPluginInfo.value.features[0],
cmd: "插件市场", cmd: "插件市场",
}); });
}; };

View File

@ -1,5 +1,5 @@
<template> <template>
<div v-show="!!options.length && searchValue" class="options" ref="scrollDom"> <div v-show="!!options.length && searchValue && !currentPlugin.name" class="options" ref="scrollDom">
<a-list item-layout="horizontal" :dataSource="options"> <a-list item-layout="horizontal" :dataSource="options">
<template #renderItem="{ item, index }"> <template #renderItem="{ item, index }">
<a-list-item <a-list-item
@ -45,6 +45,7 @@ const props = defineProps({
type: Number, type: Number,
default: 0, default: 0,
}, },
currentPlugin: {},
}); });
const renderTitle = (title) => { const renderTitle = (title) => {

View File

@ -2,12 +2,14 @@
<div class="rubick-select"> <div class="rubick-select">
<div class="select-tag" v-show="currentPlugin.cmd">{{ currentPlugin.cmd }}</div> <div class="select-tag" v-show="currentPlugin.cmd">{{ currentPlugin.cmd }}</div>
<a-input <a-input
id="search"
class="main-input" class="main-input"
placeholder="Hi, Rubick2" placeholder="Hi, Rubick2"
@change="(e) => changeValue(e)" @input="(e) => changeValue(e)"
@keydown.down="() => emit('changeCurrent', 1)" @keydown.down="() => emit('changeCurrent', 1)"
@keydown.up="() => emit('changeCurrent', -1)" @keydown.up="() => emit('changeCurrent', -1)"
@keydown="checkNeedInit" @keydown="checkNeedInit"
:value="searchValue"
> >
<template #suffix> <template #suffix>
<div @click="() => emit('openMenu')" class="suffix-tool" > <div @click="() => emit('openMenu')" class="suffix-tool" >
@ -24,22 +26,22 @@
import { defineProps, defineEmits, ref } from "vue"; import { defineProps, defineEmits, ref } from "vue";
import { ipcRenderer } from "electron"; import { ipcRenderer } from "electron";
defineProps({ const props = defineProps({
searchValue: {
type: [String, Number],
default: "",
},
currentPlugin: {}, currentPlugin: {},
}); });
const searchValue = ref("");
const changeValue = (e) => { const changeValue = (e) => {
emit("onSearch", e); emit("onSearch", e);
searchValue.value = e.target.value;
}; };
const emit = defineEmits(["onSearch", "changeCurrent", "openMenu", "changeSelect"]); const emit = defineEmits(["onSearch", "changeCurrent", "openMenu", "changeSelect"]);
const checkNeedInit = (e) => { const checkNeedInit = (e) => {
console.log(e.keyCode); if (props.searchValue === "" && e.keyCode === 8) {
if (searchValue.value === "" && e.keyCode === 8) {
closeTag(); closeTag();
} }
}; };

View File

@ -1,21 +1,13 @@
import { reactive, toRefs, toRaw } from "vue"; import { reactive, toRefs, ref } from "vue";
import { nativeImage, remote, ipcRenderer } from "electron"; import { nativeImage, remote, ipcRenderer } from "electron";
import { appSearch, PluginHandler } from "@/core"; import { appSearch, PluginHandler } from "@/core";
import path from "path"; import path from "path";
import throttle from "lodash.throttle";
import commonConst from "@/common/utils/commonConst"; import commonConst from "@/common/utils/commonConst";
import searchManager from "./search";
import optionsManager from "./options";
const appPath = remote.app.getPath("cache"); const appPath = remote.app.getPath("cache");
function searchKeyValues(lists, value) {
return lists.filter((item) => {
if (typeof item === "string") {
return item.toLowerCase().indexOf(value.toLowerCase()) >= 0;
}
return item.type.toLowerCase().indexOf(value.toLowerCase()) >= 0;
});
}
const createPluginManager = (): any => { const createPluginManager = (): any => {
const baseDir = path.join(appPath, "./rubick-plugins"); const baseDir = path.join(appPath, "./rubick-plugins");
const pluginInstance = new PluginHandler({ const pluginInstance = new PluginHandler({
@ -25,100 +17,47 @@ const createPluginManager = (): any => {
const state: any = reactive({ const state: any = reactive({
appList: [], appList: [],
plugins: [], plugins: [],
options: [],
searchValue: "",
localPlugins: [], localPlugins: [],
currentPlugin: {}, currentPlugin: {},
}); });
const appList = ref([]);
const initPlugins = async () => { const initPlugins = async () => {
state.appList = await appSearch(nativeImage); appList.value = await appSearch(nativeImage);
}; };
const addPlugin = (plugin: any) => { const openPlugin = (plugin) => {
state.plugins.unshift(plugin); if (plugin.pluginType === "ui") {
}; state.currentPlugin = plugin;
ipcRenderer.sendSync("msg-trigger", {
const removePlugin = (plugin: any) => { type: "openPlugin",
// todo plugin: JSON.parse(
}; JSON.stringify({
...plugin,
const onSearch = throttle((e) => { ext: {
const value = e.target.value; code: plugin.feature.code,
state.searchValue = value; type: plugin.cmd.type || "text",
if (!value) return; payload: null,
state.localPlugins = remote.getGlobal("LOCAL_PLUGINS").getLocalPlugins();
let options: any = [];
// todo 先搜索 plugin
state.localPlugins.forEach((plugin) => {
const feature = plugin.features;
feature.forEach((fe) => {
const cmds = searchKeyValues(fe.cmds, value);
options = [
...options,
...cmds.map((cmd) => ({
name: cmd,
value: "plugin",
icon: plugin.logo,
desc: fe.explain,
type: plugin.pluginType,
click: () => {
const pluginPath = path.resolve(
pluginInstance.baseDir,
"node_modules",
plugin.name
);
openPlugin({
...toRaw(plugin),
indexPath: `file://${path.join(
pluginPath,
"./",
plugin.main
)}`,
cmd,
feature: fe,
});
}, },
})), })
]; ),
}); });
}); // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// todo 再搜索 app // @ts-ignore
const descMap = new Map(); // document.getElementById("search").value = "";
options = [ // state.searchValue = "";
...options, }
...state.appList };
.filter((plugin) => {
if (!descMap.get(plugin)) {
descMap.set(plugin, true);
let has = false;
plugin.keyWords.some((keyWord) => {
if (
keyWord
.toLocaleUpperCase()
.indexOf(value.toLocaleUpperCase()) >= 0
) {
has = keyWord;
plugin.name = keyWord;
return true;
}
return false;
});
return has;
} else {
return false;
}
})
.map((plugin) => {
plugin.click = () => {
openPlugin(plugin);
};
return plugin;
}),
];
state.options = options;
}, 500);
const { searchValue, onSearch } = searchManager();
const { options } = optionsManager({
searchValue,
baseDir,
appList,
openPlugin,
});
// plugin operation
const getPluginInfo = async ({ pluginName, pluginPath }) => { const getPluginInfo = async ({ pluginName, pluginPath }) => {
const pluginInfo = await pluginInstance.getAdapterInfo(pluginName, pluginPath); const pluginInfo = await pluginInstance.getAdapterInfo(pluginName, pluginPath);
return { return {
@ -129,20 +68,18 @@ const createPluginManager = (): any => {
}; };
}; };
const openPlugin = (plugin) => {
if (plugin.pluginType === "ui") {
state.currentPlugin = plugin;
ipcRenderer.sendSync("msg-trigger", {
type: "openPlugin",
plugin: JSON.parse(JSON.stringify(plugin)),
});
}
};
const changeSelect = (select) => { const changeSelect = (select) => {
state.currentPlugin = select; state.currentPlugin = select;
}; };
const addPlugin = (plugin: any) => {
state.plugins.unshift(plugin);
};
const removePlugin = (plugin: any) => {
// todo
};
return { return {
...toRefs(state), ...toRefs(state),
initPlugins, initPlugins,
@ -152,6 +89,8 @@ const createPluginManager = (): any => {
getPluginInfo, getPluginInfo,
openPlugin, openPlugin,
changeSelect, changeSelect,
options,
searchValue,
}; };
}; };

View File

@ -0,0 +1,100 @@
import { ref, toRaw, toRefs, watch } from "vue";
import throttle from "lodash.throttle";
import { remote } from "electron";
import path from "path";
function searchKeyValues(lists, value) {
return lists.filter((item) => {
if (typeof item === "string") {
return item.toLowerCase().indexOf(value.toLowerCase()) >= 0;
}
return item.type.toLowerCase().indexOf(value.toLowerCase()) >= 0;
});
}
const optionsManager = ({ searchValue, baseDir, appList, openPlugin }) => {
const optionsRef = ref([]);
watch(searchValue, () => search(searchValue.value));
// search Input operation
const search = throttle((value) => {
if (!value) return;
const localPlugins = remote.getGlobal("LOCAL_PLUGINS").getLocalPlugins();
let options: any = [];
// todo 先搜索 plugin
localPlugins.forEach((plugin) => {
const feature = plugin.features;
feature.forEach((fe) => {
const cmds = searchKeyValues(fe.cmds, value);
options = [
...options,
...cmds.map((cmd) => ({
name: cmd,
value: "plugin",
icon: plugin.logo,
desc: fe.explain,
type: plugin.pluginType,
click: () => {
const pluginPath = path.resolve(
baseDir,
"node_modules",
plugin.name
);
openPlugin({
...toRaw(plugin),
indexPath: `file://${path.join(
pluginPath,
"./",
plugin.main
)}`,
cmd,
feature: fe,
});
},
})),
];
});
});
// todo 再搜索 app
const appPlugins = appList.value || [];
const descMap = new Map();
options = [
...options,
...appPlugins
.filter((plugin) => {
if (!descMap.get(plugin)) {
descMap.set(plugin, true);
let has = false;
plugin.keyWords.some((keyWord) => {
if (
keyWord
.toLocaleUpperCase()
.indexOf(value.toLocaleUpperCase()) >= 0
) {
has = keyWord;
plugin.name = keyWord;
return true;
}
return false;
});
return has;
} else {
return false;
}
})
.map((plugin) => {
plugin.click = () => {
openPlugin(plugin);
};
return plugin;
}),
];
optionsRef.value = options;
}, 500);
return {
options: optionsRef,
};
};
export default optionsManager;

View File

@ -0,0 +1,20 @@
import { reactive, toRefs } from "vue";
const searchManager = () => {
const state = reactive({
searchValue: "",
});
// search Input operation
const onSearch = (e) => {
const value = e.target.value;
state.searchValue = value;
};
return {
...toRefs(state),
onSearch,
};
};
export default searchManager;