支持文件检索呼起插件

This commit is contained in:
muwoo 2021-12-20 18:33:00 +08:00
parent ced8aa846b
commit ff118dfe2d
25 changed files with 351 additions and 70 deletions

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "rubick",
"version": "2.0.0",
"version": "2.0.1-beta.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -1,6 +1,6 @@
{
"name": "rubick",
"version": "2.0.1-beta.3",
"version": "2.0.1-beta.4",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",

View File

@ -132,4 +132,6 @@ window.rubick = {
shellOpenPath(path) {
shell.openPath(path);
},
getLocalId: () => ipcSendSync("getLocalId"),
};

View File

@ -1 +1 @@
<!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"><link rel="icon" href="favicon.ico"><title>tpl</title><link href="css/app.f5fd5a5f.css" rel="preload" as="style"><link href="js/app.845a0078.js" rel="preload" as="script"><link href="js/chunk-vendors.d5af439e.js" rel="preload" as="script"><link href="css/app.f5fd5a5f.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but tpl doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.d5af439e.js"></script><script src="js/app.845a0078.js"></script></body></html>
<!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"><link rel="icon" href="favicon.ico"><title>tpl</title><link href="css/app.f5fd5a5f.css" rel="preload" as="style"><link href="js/app.6e04bbe2.js" rel="preload" as="script"><link href="js/chunk-vendors.88fb06db.js" rel="preload" as="script"><link href="css/app.f5fd5a5f.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but tpl doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.88fb06db.js"></script><script src="js/app.6e04bbe2.js"></script></body></html>

View File

@ -0,0 +1,2 @@
(function(e){function t(t){for(var r,a,u=t[0],i=t[1],l=t[2],d=0,p=[];d<u.length;d++)a=u[d],Object.prototype.hasOwnProperty.call(c,a)&&c[a]&&p.push(c[a][0]),c[a]=0;for(r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r]);s&&s(t);while(p.length)p.shift()();return o.push.apply(o,l||[]),n()}function n(){for(var e,t=0;t<o.length;t++){for(var n=o[t],r=!0,u=1;u<n.length;u++){var i=n[u];0!==c[i]&&(r=!1)}r&&(o.splice(t--,1),e=a(a.s=n[0]))}return e}var r={},c={app:0},o=[];function a(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,a),n.l=!0,n.exports}a.m=e,a.c=r,a.d=function(e,t,n){a.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},a.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,t){if(1&t&&(e=a(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(a.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)a.d(n,r,function(t){return e[t]}.bind(null,r));return n},a.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return a.d(t,"a",t),t},a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.p="";var u=window["webpackJsonp"]=window["webpackJsonp"]||[],i=u.push.bind(u);u.push=t,u=u.slice();for(var l=0;l<u.length;l++)t(u[l]);var s=i;o.push([0,"chunk-vendors"]),n()})({0:function(e,t,n){e.exports=n("cd49")},"2fb6":function(e,t,n){},3809:function(e,t,n){"use strict";n("2fb6")},"3ac0":function(e,t,n){},cd49:function(e,t,n){"use strict";n.r(t);n("e260"),n("e6cf"),n("cca6"),n("a79d");var r=n("7a23"),c=n("6c02"),o={setup:function(e){var t=Object(c["d"])();return window.rubick.onPluginEnter((function(e){var n=e.code,r=e.type,c=e.payload,o=window.exports[n];t.push({name:o.mode,params:{code:n,type:r,payload:c}})})),function(e,t){var n=Object(r["w"])("router-view");return Object(r["r"])(),Object(r["d"])(n)}}};n("da18");const a=o;var u=a,i=(n("ac1f"),n("841c"),n("a4d3"),n("e01a"),{class:"list-container"}),l={class:"options"},s=["onClick"],d=["src"],p={class:"content"},f={class:"title"},v={class:"desc"},b=Object(r["h"])({setup:function(e){var t=window.require("electron"),n=t.ipcRenderer,o=Object(c["c"])(),a=60,u=10,b=60,O=o.params,j=O.code,y=O.type,w=O.payload,h=window.exports[j];window.rubick.setExpendHeight(b);var g=Object(r["u"])([]);Object(r["B"])([g],(function(){var e=g.value.length>u?u*a:a*g.value.length;window.rubick.setExpendHeight(b+e)})),h.args.enter&&h.args.enter({code:j,type:y,payload:w},(function(e){g.value=e}));var m=Object(r["u"])(0);n.on("changeCurrent",(function(e,t){m.value+t>g.value.length-1||g.value+t<0||(m.value=m.value+t)})),window.rubick.setSubInput((function(e){var t=e.text;h.args.search&&h.args.search({code:j,type:"",payload:[]},t,(function(e){g.value=e||[]}))}),"搜索");var k=function(e){h.args.select&&h.args.select({code:j,type:"",payload:[]},e)},x=function(e){if("Enter"===e.code)return k(g.value[m.value]);var t=0;"ArrowDown"===e.code&&(t=1),"ArrowUp"===e.code&&(t=-1),g.value.length&&(m.value+t>g.value.length-1||m.value+t<0||(m.value=m.value+t))};return window.addEventListener("keydown",x),Object(r["o"])((function(){window.removeEventListener("keydown",x)})),function(e,t){return Object(r["r"])(),Object(r["f"])("div",i,[Object(r["C"])(Object(r["g"])("div",l,[(Object(r["r"])(!0),Object(r["f"])(r["a"],null,Object(r["v"])(g.value,(function(e,t){return Object(r["r"])(),Object(r["f"])("div",{key:t,class:Object(r["m"])(m.value===t?"active op-item":"op-item"),onClick:function(t){return k(e)}},[e.icon?(Object(r["r"])(),Object(r["f"])("img",{key:0,class:"icon",src:e.icon},null,8,d)):Object(r["e"])("",!0),Object(r["g"])("div",p,[Object(r["g"])("div",f,Object(r["y"])(e.title),1),Object(r["g"])("div",v,Object(r["y"])(decodeURIComponent(e.description)),1)])],10,s)})),128))],512),[[r["A"],!!(g.value||[]).length]])])}}});n("3809");const O=b;var j=O,y={class:"home"};function w(e,t){return Object(r["r"])(),Object(r["f"])("div",y)}var h=n("6b0d"),g=n.n(h);const m={},k=g()(m,[["render",w]]);var x=k,P=[{path:"/list",name:"list",component:j},{path:"/doc",name:"doc",component:x}],E=Object(c["a"])({history:Object(c["b"])(),routes:P}),S=E,_=n("5502"),C=Object(_["a"])({state:{},mutations:{},actions:{},modules:{}});Object(r["c"])(u).use(C).use(S).mount("#app")},da18:function(e,t,n){"use strict";n("3ac0")}});
//# sourceMappingURL=app.6e04bbe2.js.map

File diff suppressed because one or more lines are too long

View File

@ -1,2 +0,0 @@
(function(e){function t(t){for(var r,u,a=t[0],i=t[1],l=t[2],d=0,p=[];d<a.length;d++)u=a[d],Object.prototype.hasOwnProperty.call(c,u)&&c[u]&&p.push(c[u][0]),c[u]=0;for(r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r]);s&&s(t);while(p.length)p.shift()();return o.push.apply(o,l||[]),n()}function n(){for(var e,t=0;t<o.length;t++){for(var n=o[t],r=!0,a=1;a<n.length;a++){var i=n[a];0!==c[i]&&(r=!1)}r&&(o.splice(t--,1),e=u(u.s=n[0]))}return e}var r={},c={app:0},o=[];function u(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,u),n.l=!0,n.exports}u.m=e,u.c=r,u.d=function(e,t,n){u.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},u.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},u.t=function(e,t){if(1&t&&(e=u(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(u.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)u.d(n,r,function(t){return e[t]}.bind(null,r));return n},u.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return u.d(t,"a",t),t},u.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},u.p="";var a=window["webpackJsonp"]=window["webpackJsonp"]||[],i=a.push.bind(a);a.push=t,a=a.slice();for(var l=0;l<a.length;l++)t(a[l]);var s=i;o.push([0,"chunk-vendors"]),n()})({0:function(e,t,n){e.exports=n("cd49")},2874:function(e,t,n){},"2f93":function(e,t,n){"use strict";n("4016")},4016:function(e,t,n){},5490:function(e,t,n){"use strict";n("2874")},cd49:function(e,t,n){"use strict";n.r(t);n("e260"),n("e6cf"),n("cca6"),n("a79d");var r=n("7a23"),c=n("6c02"),o={setup:function(e){var t=Object(c["d"])();return window.rubick.onPluginEnter((function(e){var n=e.code,r=window.exports[n];t.push({name:r.mode,params:{code:n}})})),function(e,t){var n=Object(r["v"])("router-view");return Object(r["q"])(),Object(r["d"])(n)}}};n("5490");const u=o;var a=u,i=(n("ac1f"),n("841c"),n("a4d3"),n("e01a"),{class:"list-container"}),l={class:"options"},s=["onClick"],d=["src"],p={class:"content"},f={class:"title"},v={class:"desc"},b=Object(r["g"])({setup:function(e){var t=window.require("electron"),n=t.ipcRenderer,o=Object(c["c"])(),u=60,a=10,b=60,O=o.params.code,j=window.exports[O];window.rubick.setExpendHeight(b);var w=Object(r["t"])([]);j.args.enter&&j.args.enter({code:O,type:"",payload:[]},(function(e){e.value=e}));var h=Object(r["t"])(0);n.on("changeCurrent",(function(e,t){h.value+t>w.value.length-1||w.value+t<0||(h.value=h.value+t)})),window.rubick.setSubInput((function(e){var t=e.text;j.args.search&&j.args.search({code:O,type:"",payload:[]},t,(function(e){w.value=e||[];var t=w.value.length>a?a*u:u*w.value.length;window.rubick.setExpendHeight(b+t)}))}),"搜索");var g=function(e){j.args.select&&j.args.select({code:O,type:"",payload:[]},e)},y=function(e){if("Enter"===e.code)return g(w.value[h.value]);var t=0;"ArrowDown"===e.code&&(t=1),"ArrowUp"===e.code&&(t=-1),w.value.length&&(h.value+t>w.value.length-1||h.value+t<0||(h.value=h.value+t))};return window.addEventListener("keydown",y),Object(r["n"])((function(){window.removeEventListener("keydown",y)})),function(e,t){return Object(r["q"])(),Object(r["e"])("div",i,[Object(r["B"])(Object(r["f"])("div",l,[(Object(r["q"])(!0),Object(r["e"])(r["a"],null,Object(r["u"])(w.value,(function(e,t){return Object(r["q"])(),Object(r["e"])("div",{key:t,class:Object(r["l"])(h.value===t?"active op-item":"op-item"),onClick:function(t){return g(e)}},[Object(r["f"])("img",{class:"icon",src:e.icon},null,8,d),Object(r["f"])("div",p,[Object(r["f"])("div",f,Object(r["x"])(e.title),1),Object(r["f"])("div",v,Object(r["x"])(decodeURIComponent(e.description)),1)])],10,s)})),128))],512),[[r["z"],!!(w.value||[]).length]])])}}});n("2f93");const O=b;var j=O,w={class:"home"};function h(e,t){return Object(r["q"])(),Object(r["e"])("div",w)}var g=n("6b0d"),y=n.n(g);const m={},x=y()(m,[["render",h]]);var k=x,P=[{path:"/list",name:"list",component:j},{path:"/doc",name:"doc",component:k}],q=Object(c["a"])({history:Object(c["b"])(),routes:P}),E=q,S=n("5502"),_=Object(S["a"])({state:{},mutations:{},actions:{},modules:{}});Object(r["c"])(a).use(_).use(E).mount("#app")}});
//# sourceMappingURL=app.845a0078.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,49 @@
import commonConst from "./commonConst";
import { clipboard, remote } from "electron";
import plist from "plist";
import fs from "fs";
import path from "path";
import ofs from "original-fs";
export default function getCopyFiles(): Array<any> | null {
let fileInfo;
if (commonConst.macOS()) {
if (!clipboard.has("NSFilenamesPboardType")) return null;
const result = clipboard.read("NSFilenamesPboardType");
if (!result) return null;
try {
fileInfo = plist.parse(result);
} catch (e) {
return null;
}
} else if (commonConst.windows()) {
// todo
} else {
if (!commonConst.linux()) return null;
if (!clipboard.has("text/uri-list")) return null;
const result = clipboard.read("text/uri-list").match(/^file:\/\/\/.*/gm);
if (!result || !result.length) return null;
fileInfo = result.map((e) =>
decodeURIComponent(e).replace(/^file:\/\//, "")
);
}
if (!Array.isArray(fileInfo)) return null;
const target: any = fileInfo
.map((p) => {
if (!fs.existsSync(p)) return false;
let info;
try {
info = ofs.lstatSync(p);
} catch (e) {
return false;
}
return {
isFile: info.isFile(),
isDirectory: info.isDirectory(),
name: path.basename(p) || p,
path: p,
};
})
.filter(Boolean);
return target.length ? target : null;
}

View File

@ -10,7 +10,10 @@
:searchValue="searchValue"
:placeholder="placeholder"
:pluginLoading="pluginLoading"
:clipboardFile="clipboardFile || []"
@choosePlugin="choosePlugin"
@focus="searchFocus"
@clearClipbord="clearClipboardFile"
/>
</div>
<Result
@ -18,6 +21,7 @@
:searchValue="searchValue"
:currentSelect="currentSelect"
:options="options"
:clipboardFile="clipboardFile || []"
/>
</div>
</template>
@ -41,6 +45,9 @@ const {
currentPlugin,
placeholder,
pluginLoading,
searchFocus,
clipboardFile,
clearClipboardFile,
} = createPluginManager();
initPlugins();
@ -57,13 +64,13 @@ getPluginInfo({
remote.getGlobal("LOCAL_PLUGINS").addPlugin(res);
});
watch([searchValue], () => {
watch([options], () => {
currentSelect.value = 0;
if (currentPlugin.value.name) return;
nextTick(() => {
ipcRenderer.sendSync("msg-trigger", {
type: "setExpendHeight",
data: getWindowHeight(searchValue.value ? options.value : []),
data: getWindowHeight(options.value),
});
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -1,5 +1,5 @@
<template>
<div v-show="!!options.length && searchValue && !currentPlugin.name" class="options" ref="scrollDom">
<div v-show="!!options.length && (searchValue || !!clipboardFile.length) && !currentPlugin.name" class="options" ref="scrollDom">
<a-list item-layout="horizontal" :dataSource="options">
<template #renderItem="{ item, index }">
<a-list-item
@ -46,10 +46,12 @@ const props = defineProps({
default: 0,
},
currentPlugin: {},
clipboardFile: () => [],
});
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>`;

View File

@ -1,6 +1,10 @@
<template>
<div class="rubick-select">
<div class="select-tag" v-show="currentPlugin.cmd">{{ currentPlugin.cmd }}</div>
<div class="clipboard-tag" v-if="!!clipboardFile.length">
<img :src="clipboardFile[0].isFile ? require('../assets/file.png') : require('../assets/folder.png')" />
{{ clipboardFile[0].name }}
</div>
<a-input
id="search"
class="main-input"
@ -11,6 +15,7 @@
:value="searchValue"
:placeholder="placeholder || 'Hi, Rubick2'"
@keypress.enter="(e) => keydownEvent(e)"
@focus="emit('focus')"
>
<template #suffix>
<div class="suffix-tool" >
@ -36,15 +41,16 @@
</template>
<script setup lang="ts">
import { defineProps, defineEmits, ref } from "vue";
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");
const { Menu } = remote;
const config = ref(opConfig.get());
const props = defineProps({
const props: any = defineProps({
searchValue: {
type: [String, Number],
default: "",
@ -55,6 +61,7 @@ const props = defineProps({
},
currentPlugin: {},
pluginLoading: Boolean,
clipboardFile: () => [],
});
const changeValue = (e) => {
@ -69,11 +76,12 @@ const emit = defineEmits([
"openMenu",
"changeSelect",
"choosePlugin",
"focus",
]);
const keydownEvent = (e, index) => {
const { ctrlKey, shiftKey, altKey, metaKey } = e;
const modifiers = [];
const modifiers: Array<string> = [];
ctrlKey && modifiers.push("control");
shiftKey && modifiers.push("shift");
altKey && modifiers.push("alt");
@ -98,7 +106,7 @@ const checkNeedInit = (e) => {
}
};
const targetSearch = ({ value, type }) => {
const targetSearch = ({ value }) => {
if (props.currentPlugin.name) {
return ipcRenderer.sendSync("msg-trigger", {
type: "sendSubInputChangeEvent",
@ -109,13 +117,14 @@ const targetSearch = ({ value, type }) => {
const closeTag = () => {
emit("changeSelect", {});
emit("clearClipbord");
ipcRenderer.send("msg-trigger", {
type: "removePlugin",
});
};
const showSeparate = () => {
let pluginMenu = [
let pluginMenu: any = [
{
label: config.value.perf.common.hideOnBlur ? "钉住" : "自动隐藏",
click: changeHideOnBlur,
@ -233,5 +242,22 @@ const newWindow = () => {
left: 0;
}
}
.clipboard-tag {
white-space: pre;
user-select: none;
font-size: 16px;
height: 32px;
position: relative;
align-items: center;
display: flex;
border: 1px solid #e6e6e6;
padding: 0 8px;
margin-right: 12px;
img {
width: 24px;
height: 24px;
margin-right: 6px;
}
}
}
</style>

View File

@ -0,0 +1,133 @@
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 = () => {
if (currentPlugin.value.name) return;
const fileList = getCopyFiles();
// 拷贝的是文件
if (fileList) {
window.setSubInputValue({ value: "" });
clipboardFile.value = fileList;
const localPlugins = remote.getGlobal("LOCAL_PLUGINS").getLocalPlugins();
const options: any = [
{
name: "复制路径",
value: "plugin",
icon: require("../assets/link.png"),
desc: "复制路径到剪切板",
click: () => {
clipboard.writeText(fileList.map(file => file.path).join(","));
ipcRenderer.send("msg-trigger", { type: "hideMainWindow" });
},
},
];
// 判断复制的文件类型是否一直
const commonLen = fileList.filter(
(file) => path.extname(fileList[0].path) === path.extname(file.path)
).length;
// 复制路径
if (commonLen !== fileList.length) {
setOptionsRef(options);
return;
}
// 再正则插件
localPlugins.forEach((plugin) => {
const feature = plugin.features;
// 系统插件无 features 的情况,不需要再搜索
if (!feature) return;
feature.forEach((fe) => {
const ext = path.extname(fileList[0].path);
fe.cmds.forEach((cmd) => {
const regImg = /\.(png|jpg|gif|jpeg|webp)$/;
if (cmd.type === "img" && regImg.test(ext) && fileList.length === 1) {
options.push({
name: cmd.label,
value: "plugin",
icon: plugin.logo,
desc: fe.explain,
type: plugin.pluginType,
click: () => {
pluginClickEvent({
plugin,
fe,
cmd,
ext: {
code: fe.code,
type: cmd.type || "text",
payload: nativeImage.createFromPath(fileList[0].path).toDataURL(),
},
openPlugin,
});
clearClipboardFile();
},
});
}
// 如果是文件,且符合文件正则类型
if (
fileList.length > 1 ||
(cmd.type === "file" && new RegExp(cmd.match).test(ext))
) {
options.push({
name: cmd,
value: "plugin",
icon: plugin.logo,
desc: fe.explain,
type: plugin.pluginType,
click: () => {
pluginClickEvent({
plugin,
fe,
cmd,
ext: {
code: fe.code,
type: cmd.type || "text",
payload: fileList,
},
openPlugin,
});
clearClipboardFile();
},
});
}
});
});
});
setOptionsRef(options);
clipboard.clear();
return;
}
const clipboardType = clipboard.availableFormats();
if (!clipboardType.length) return;
if ("text/plain" === clipboardType[0]) {
const contentText = clipboard.readText();
if (contentText.trim()) {
clearClipboardFile();
window.setSubInputValue({ value: contentText });
}
}
clipboard.clear();
};
const clearClipboardFile = () => {
clipboardFile.value = [];
optionsRef.value = [];
};
return {
searchFocus,
clipboardFile,
clearClipboardFile,
};
};

View File

@ -39,7 +39,7 @@ const createPluginManager = (): any => {
plugin: JSON.parse(
JSON.stringify({
...plugin,
ext: {
ext: plugin.ext || {
code: plugin.feature.code,
type: plugin.cmd.type || "text",
payload: null,
@ -54,16 +54,21 @@ const createPluginManager = (): any => {
}
};
const { searchValue, onSearch, setSearchValue, placeholder } = searchManager();
const { options } = optionsManager({
searchValue,
appList,
openPlugin,
currentPlugin: toRefs(state).currentPlugin,
});
const { searchValue, onSearch, setSearchValue, placeholder } =
searchManager();
const { options, searchFocus, clipboardFile, clearClipboardFile } =
optionsManager({
searchValue,
appList,
openPlugin,
currentPlugin: toRefs(state).currentPlugin,
});
// plugin operation
const getPluginInfo = async ({ pluginName, pluginPath }) => {
const pluginInfo = await pluginInstance.getAdapterInfo(pluginName, pluginPath);
const pluginInfo = await pluginInstance.getAdapterInfo(
pluginName,
pluginPath
);
return {
...pluginInfo,
indexPath: commonConst.dev()
@ -115,6 +120,9 @@ const createPluginManager = (): any => {
options,
searchValue,
placeholder,
searchFocus,
clipboardFile,
clearClipboardFile,
};
};

View File

@ -1,27 +1,44 @@
import { ref, toRaw, toRefs, watch } from "vue";
import { ref, watch } from "vue";
import throttle from "lodash.throttle";
import { remote } from "electron";
import path from "path";
import { PLUGIN_INSTALL_DIR as baseDir } from "@/common/constans/renderer";
import commonConst from "@/common/utils/commonConst";
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");
return new RegExp(pattern, flags);
}
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;
if (item.type === "regex") {
return formatReg(item.match).test(value);
}
return false;
});
}
const optionsManager = ({ searchValue, appList, openPlugin, currentPlugin }) => {
const optionsManager = ({
searchValue,
appList,
openPlugin,
currentPlugin,
}) => {
const optionsRef = ref([]);
watch(searchValue, () => search(searchValue.value));
// search Input operation
const search = throttle((value) => {
if (currentPlugin.value.name) return;
if (!value) return;
if (clipboardFile.value.length) return;
if (!value) {
optionsRef.value = [];
return;
}
const localPlugins = remote.getGlobal("LOCAL_PLUGINS").getLocalPlugins();
let options: any = [];
// todo 先搜索 plugin
@ -34,34 +51,25 @@ const optionsManager = ({ searchValue, appList, openPlugin, currentPlugin }) =>
options = [
...options,
...cmds.map((cmd) => ({
name: cmd,
name: cmd.label || cmd,
value: "plugin",
icon: plugin.logo,
desc: fe.explain,
type: plugin.pluginType,
click: () => {
const pluginPath = path.resolve(
baseDir,
"node_modules",
plugin.name
);
const pluginDist = {
...toRaw(plugin),
indexPath: `file://${path.join(
pluginPath,
"./",
plugin.main || ""
)}`,
pluginClickEvent({
plugin,
fe,
cmd,
feature: fe,
};
// 模板文件
if (!plugin.main) {
pluginDist.tplPath = commonConst.dev()
? "http://localhost:8082/#/"
: `file://${__static}/tpl/index.html`;
}
openPlugin(pluginDist);
ext: cmd.type
? {
code: fe.code,
type: cmd.type || "text",
payload: searchValue.value,
}
: null,
openPlugin,
});
},
})),
];
@ -104,8 +112,22 @@ const optionsManager = ({ searchValue, appList, openPlugin, currentPlugin }) =>
optionsRef.value = options;
}, 500);
const setOptionsRef = (options) => {
optionsRef.value = options;
};
const { searchFocus, clipboardFile, clearClipboardFile } = useFocus({
currentPlugin,
optionsRef,
openPlugin,
setOptionsRef,
});
return {
options: optionsRef,
searchFocus,
clipboardFile,
clearClipboardFile,
};
};

View File

@ -0,0 +1,30 @@
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 pluginDist = {
...toRaw(plugin),
indexPath: `file://${path.join(
pluginPath,
"./",
plugin.main || ""
)}`,
cmd: cmd.label || cmd,
feature: fe,
ext,
};
// 模板文件
if (!plugin.main) {
pluginDist.tplPath = commonConst.dev()
? "http://localhost:8082/#/"
: `file://${__static}/tpl/index.html`;
}
openPlugin(pluginDist);
}

View File

@ -6,12 +6,12 @@
import { useRouter } from "vue-router";
const router = useRouter();
window.rubick.onPluginEnter(({ code }) => {
window.rubick.onPluginEnter(({ code, type, payload }) => {
const current = window.exports[code];
router.push({
name: current.mode,
params: {
code,
code, type, payload
},
});
});

View File

@ -7,7 +7,7 @@
v-for="(item, index) in lists"
@click="select(item)"
>
<img class="icon" :src="item.icon" />
<img v-if="item.icon" class="icon" :src="item.icon" />
<div class="content">
<div class="title">{{ item.title }}</div>
<div class="desc">{{ decodeURIComponent(item.description) }}</div>
@ -18,7 +18,7 @@
</template>
<script setup lang="ts">
import { useRoute } from "vue-router";
import { ref, onBeforeUnmount } from "vue";
import { ref, onBeforeUnmount, watch } from "vue";
const { ipcRenderer } = window.require("electron");
const route = useRoute();
@ -27,14 +27,18 @@ const itemHeight = 60;
const itemMaxNum = 10;
const defaultHeight = 60;
const code = route.params.code;
const { code, type, payload } = route.params;
const current = window.exports[code];
window.rubick.setExpendHeight(defaultHeight);
const lists = ref([]);
watch([lists], () => {
const height = lists.value.length > itemMaxNum ? itemMaxNum * itemHeight : itemHeight * lists.value.length
window.rubick.setExpendHeight(defaultHeight + height);
});
current.args.enter &&
current.args.enter({ code: code, type: "", payload: [] }, (lists) => {
lists.value = lists;
current.args.enter({ code: code, type, payload }, (result) => {
lists.value = result;
});
const currentSelect = ref(0);
@ -51,8 +55,6 @@ window.rubick.setSubInput(({ text }) => {
current.args.search &&
current.args.search({ code, type: "", payload: [] }, text, (result) => {
lists.value = result || [];
const height = lists.value.length > itemMaxNum ? itemMaxNum * itemHeight : itemHeight * lists.value.length
window.rubick.setExpendHeight(defaultHeight + height);
});
}, "搜索");