mirror of
https://github.com/rubickCenter/rubick
synced 2025-10-26 14:42:43 +08:00
Compare commits
42 Commits
v2.0.1-bet
...
v2.0.4-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b43c2c0091 | ||
|
|
900a568ddf | ||
|
|
8d3d55bdd8 | ||
|
|
310dba0aa3 | ||
|
|
343079d24f | ||
|
|
c49b55992c | ||
|
|
d562d88768 | ||
|
|
554b208f80 | ||
|
|
ef563717a3 | ||
|
|
173a3a93ba | ||
|
|
cdc4fa3a09 | ||
|
|
a2d7c9b9c4 | ||
|
|
915288499e | ||
|
|
e1ccbb69a5 | ||
|
|
9613c24deb | ||
|
|
91b075a439 | ||
|
|
6cecfbf77d | ||
|
|
aada416790 | ||
|
|
65932ca22a | ||
|
|
419dc21618 | ||
|
|
313142e6f0 | ||
|
|
039b69f4be | ||
|
|
e0d0de4baf | ||
|
|
4d621c7521 | ||
|
|
cd4036a805 | ||
|
|
3e3c198a7f | ||
|
|
02dcc34a4b | ||
|
|
ba0ccbb8ff | ||
|
|
56b6ca9e89 | ||
|
|
9869d9fecf | ||
|
|
1e4757f70d | ||
|
|
6adf25dbee | ||
|
|
7fbb12d04b | ||
|
|
ded16b9580 | ||
|
|
d379c58082 | ||
|
|
8a536374ea | ||
|
|
bcfc968c9d | ||
|
|
4bf3f3a602 | ||
|
|
497de040cf | ||
|
|
a22a78fa0a | ||
|
|
d2894c66ba | ||
|
|
ff7473deb2 |
@@ -32,6 +32,8 @@ Based on electron open source toolbox, free integration of rich plug-ins, to cre
|
||||
## Installation package
|
||||
* [Rubick Mac OS](https://github.com/rubickCenter/rubick/releases)
|
||||
* [Rubick Windows](https://github.com/rubickCenter/rubick/releases)
|
||||
* [Rubick Linux](https://github.com/rubickCenter/rubick/releases)
|
||||
|
||||
|
||||
## Feature list
|
||||
- [x] Plug-in management based on npm package mode, installing plugins is as easy as installing npm packages.
|
||||
@@ -41,6 +43,8 @@ Based on electron open source toolbox, free integration of rich plug-ins, to cre
|
||||
- [x] Support searching for locally installed apps or preferences
|
||||
- [x] Support MacOS
|
||||
- [x] Support Windows
|
||||
- [x] Support Linux
|
||||
|
||||
|
||||
|
||||
## Docs
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#### 示例
|
||||
|
||||
```js
|
||||
rubcik.onPluginReady(({ code, type, payload }) => {
|
||||
rubick.onPluginReady(({ code, type, payload }) => {
|
||||
console.log('插件装配完成,已准备好')
|
||||
})
|
||||
/*
|
||||
|
||||
@@ -113,7 +113,7 @@ rubick-system-plugin-demo
|
||||
"version": "0.0.0",
|
||||
"description": "rubick 系统插件demo",
|
||||
"entry": "index.js",
|
||||
"logo": "httpss://static.91jkys.com/upload/202112/08/5bac90649c5343cabb63930b131cf8e6.png",
|
||||
"logo": "https://xxxx/upload/202112/08/5bac90649c5343cabb63930b131cf8e6.png",
|
||||
"pluginType": "system",
|
||||
"author": "muwoo",
|
||||
"homepage": ""
|
||||
@@ -171,6 +171,6 @@ $ npm link
|
||||
$ npm publish
|
||||
```
|
||||
|
||||
然后再给 [rubick-database/plugins/total-plugins.json](https://gitee.com/monkeyWang/rubick-database/blob/master/plugins/total-plugins.json) 仓库提个 `pull request`, 把你的 `package.json` 信息加入 `json` 文件内,等我们 merge 了您的提交,插件将会自动上架。
|
||||
然后再给 [rubick-database/plugins/total-plugins.json](https://gitcode.net/rubickcenter/rubick-database/-/blob/master/plugins/total-plugins.json) 仓库提个 `pull request`, 把你的 `package.json` 信息加入 `json` 文件内,等我们 merge 了您的提交,插件将会自动上架。
|
||||
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ macos 选择 `pkg` 文件,windows 选择 `exe` 文件。
|
||||
::: tip
|
||||
如果把插件发布到公网 `npm` 如果不符合您的公司安全要求,`rubick` 支持内网私有源和私有插件库,如果您需要内网部署使用,可以自行配置以下规则。
|
||||
:::
|
||||
`rubick` 依赖 `npm` 仓库做插件管理,依赖 `gitee` 做插件数据存储,所以如果要进行内网部署,主要需要替换这2个设置。详细设置:
|
||||
`rubick` 依赖 `npm` 仓库做插件管理,依赖 `gitcode` 做插件数据存储,所以如果要进行内网部署,主要需要替换这2个设置。详细设置:
|
||||
`插件市场 -> 设置 -> 内网部署设置`
|
||||
|
||||

|
||||
@@ -62,9 +62,9 @@ macos 选择 `pkg` 文件,windows 选择 `exe` 文件。
|
||||
#### 1. 替换 npm 源
|
||||
插件发布到私有 `npm` 源即可。
|
||||
|
||||
#### 2. 替换 `gitee` 源为内网 `gitlab`: database url
|
||||
#### 2. 替换 `gitcode` 源为内网 `gitlab`: database url
|
||||
|
||||
* clone 下载 rubick 插件库:[https://gitee.com/monkeyWang/rubick-database](https://gitee.com/monkeyWang/rubick-database)
|
||||
* clone 下载 rubick 插件库:[https://gitcode.net/rubickcenter/rubick-database](https://gitcode.net/rubickcenter/rubick-database)
|
||||
* 提交仓库到私有 `gitlab` 库。
|
||||
|
||||
替换格式:`https://gitlab.xxx.com/api/v4/projects/{projectId}/repository/files/` 。因为接口为 `gitlab openAPI`,所以需要填写仓库 `access_token`
|
||||
|
||||
@@ -101,5 +101,3 @@ $ npm run electron:build
|
||||
5. Make sure that running npm run prepublish outputs the correct files.
|
||||
6. Rebase before creating a PR to keep commit history clear. (Merge request to branch dev)
|
||||
7. Provide some description about your PR.
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"pluginName": "rubick 系统菜单",
|
||||
"description": "rubick 系统菜单",
|
||||
"main": "index.html",
|
||||
"logo": "https://static.91jkys.com/upload/202112/08/8a1abbb051bf4b05bbc9bbf66ade63f2.png",
|
||||
"logo": "https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/acb761082f4a4b46847e7cd8b180f63c~tplv-k3u1fbpfcp-watermark.image",
|
||||
"version": "0.0.0",
|
||||
"preload":"preload.js",
|
||||
"pluginType": "ui",
|
||||
|
||||
20
feature/src/assets/common.less
Normal file
20
feature/src/assets/common.less
Normal file
@@ -0,0 +1,20 @@
|
||||
.left-menu {
|
||||
width: 200px;
|
||||
height: 100vh;
|
||||
.search-container {
|
||||
padding: 10px;
|
||||
}
|
||||
.ant-input-affix-wrapper {
|
||||
border: none;
|
||||
}
|
||||
:deep(.ant-menu) {
|
||||
background: #F3EFEF;
|
||||
.ant-menu-item-selected {
|
||||
background-color: #E2E2E2;
|
||||
color: #141414;
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import axios from "axios";
|
||||
|
||||
let baseURL = "https://gitee.com/monkeyWang/rubick-database/raw/master";
|
||||
let baseURL = "https://gitcode.net/rubickcenter/rubick-database/-/raw/master";
|
||||
let access_token = "";
|
||||
|
||||
try {
|
||||
@@ -12,7 +12,7 @@ try {
|
||||
}
|
||||
|
||||
const instance = axios.create({
|
||||
baseURL: baseURL || "https://gitee.com/monkeyWang/rubick-database/raw/master",
|
||||
baseURL: baseURL || "https://gitcode.net/rubickcenter/rubick-database/-/raw/master",
|
||||
});
|
||||
|
||||
export default {
|
||||
|
||||
11
feature/src/shims-vue.d.ts
vendored
11
feature/src/shims-vue.d.ts
vendored
@@ -8,5 +8,14 @@ declare module '*.vue' {
|
||||
declare module 'axios'
|
||||
|
||||
interface Window {
|
||||
rubick: any
|
||||
rubick: any;
|
||||
market: any
|
||||
}
|
||||
|
||||
namespace Market {
|
||||
interface Plugin {
|
||||
isdownload?: boolean;
|
||||
name?: string;
|
||||
isloading: boolean
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createStore } from "vuex";
|
||||
import request from "@/assets/request";
|
||||
|
||||
const isDownload = (item: any, targets: any[]) => {
|
||||
const isDownload = (item: Market.Plugin, targets: any[]) => {
|
||||
let isDownload = false;
|
||||
targets.some((plugin) => {
|
||||
if (plugin.name === item.name) {
|
||||
@@ -27,11 +27,11 @@ export default createStore({
|
||||
actions: {
|
||||
async init({ commit }) {
|
||||
const totalPlugins = await request.getTotalPlugins();
|
||||
const localPlugins = (window as any).market.getLocalPlugins();
|
||||
const localPlugins = window.market.getLocalPlugins();
|
||||
|
||||
totalPlugins.forEach(
|
||||
(origin: { isdwonload?: any; name?: any; isloading: boolean }) => {
|
||||
origin.isdwonload = isDownload(origin, localPlugins);
|
||||
(origin: Market.Plugin) => {
|
||||
origin.isdownload = isDownload(origin, localPlugins);
|
||||
origin.isloading = false;
|
||||
}
|
||||
);
|
||||
@@ -43,7 +43,7 @@ export default createStore({
|
||||
startDownload({ commit, state }, name) {
|
||||
const totalPlugins = JSON.parse(JSON.stringify(state.totalPlugins));
|
||||
totalPlugins.forEach(
|
||||
(origin: { isdwonload?: any; name?: any; isloading: boolean }) => {
|
||||
(origin: Market.Plugin) => {
|
||||
if (origin.name === name) {
|
||||
origin.isloading = true;
|
||||
}
|
||||
@@ -55,9 +55,9 @@ export default createStore({
|
||||
},
|
||||
|
||||
startUnDownload({ commit, state }, name) {
|
||||
const localPlugins = (window as any).market.getLocalPlugins();
|
||||
const localPlugins = window.market.getLocalPlugins();
|
||||
localPlugins.forEach(
|
||||
(origin: { isdwonload?: any; name?: any; isloading: boolean }) => {
|
||||
(origin: Market.Plugin) => {
|
||||
if (origin.name === name) {
|
||||
origin.isloading = true;
|
||||
}
|
||||
@@ -71,14 +71,14 @@ export default createStore({
|
||||
successDownload({ commit, state }, name) {
|
||||
const totalPlugins = JSON.parse(JSON.stringify(state.totalPlugins));
|
||||
totalPlugins.forEach(
|
||||
(origin: { isdwonload?: any; name?: any; isloading: boolean }) => {
|
||||
(origin: Market.Plugin) => {
|
||||
if (origin.name === name) {
|
||||
origin.isloading = false;
|
||||
origin.isdwonload = true;
|
||||
origin.isdownload = true;
|
||||
}
|
||||
}
|
||||
);
|
||||
const localPlugins = (window as any).market.getLocalPlugins();
|
||||
const localPlugins = window.market.getLocalPlugins();
|
||||
|
||||
commit("commonUpdate", {
|
||||
totalPlugins,
|
||||
@@ -86,12 +86,12 @@ export default createStore({
|
||||
});
|
||||
},
|
||||
async updateLocalPlugin({ commit }) {
|
||||
const localPlugins = (window as any).market.getLocalPlugins();
|
||||
const localPlugins = window.market.getLocalPlugins();
|
||||
const totalPlugins = await request.getTotalPlugins();
|
||||
|
||||
totalPlugins.forEach(
|
||||
(origin: { isdwonload?: any; name?: any; isloading: boolean }) => {
|
||||
origin.isdwonload = isDownload(origin, localPlugins);
|
||||
(origin: Market.Plugin) => {
|
||||
origin.isdownload = isDownload(origin, localPlugins);
|
||||
origin.isloading = false;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
<template>
|
||||
<div class="installed">
|
||||
<div v-if="!localPlugins.length">
|
||||
<a-result status="404" title="暂无任何插件" sub-title="去插件市场选择安装合适的插件吧!" />
|
||||
<a-result
|
||||
status="404"
|
||||
title="暂无任何插件"
|
||||
sub-title="去插件市场选择安装合适的插件吧!"
|
||||
/>
|
||||
</div>
|
||||
<div class="container" v-else>
|
||||
<div class="installed-list">
|
||||
@@ -44,8 +48,7 @@
|
||||
@click="deletePlugin(pluginDetail)"
|
||||
>
|
||||
移除
|
||||
</a-button
|
||||
>
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<a-tabs default-active-key="1">
|
||||
@@ -61,6 +64,14 @@
|
||||
:key="cmd"
|
||||
v-for="cmd in item.cmds"
|
||||
@close="removeFeature(cmd)"
|
||||
@click="
|
||||
!cmd.label &&
|
||||
openPlugin({
|
||||
code: item.code,
|
||||
cmd
|
||||
})
|
||||
"
|
||||
:class="{ executable: !cmd.label }"
|
||||
:color="!cmd.label && '#87d068'"
|
||||
>
|
||||
{{ cmd.label || cmd }}
|
||||
@@ -74,7 +85,6 @@
|
||||
</a-tabs>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -83,6 +93,7 @@ import { useStore } from "vuex";
|
||||
import { computed, ref } from "vue";
|
||||
import path from "path";
|
||||
import MarkdownIt from "markdown-it";
|
||||
const { ipcRenderer } = window.require("electron");
|
||||
|
||||
const { remote } = window.require("electron");
|
||||
const fs = window.require("fs");
|
||||
@@ -94,11 +105,11 @@ const baseDir = path.join(appPath, "./rubick-plugins");
|
||||
const store = useStore();
|
||||
const localPlugins = computed(() =>
|
||||
store.state.localPlugins.filter(
|
||||
(plugin) => plugin.name !== "rubick-system-feature"
|
||||
plugin => plugin.name !== "rubick-system-feature"
|
||||
)
|
||||
);
|
||||
const updateLocalPlugin = () => store.dispatch("updateLocalPlugin");
|
||||
const startUnDownload = (name) => store.dispatch("startUnDownload", name);
|
||||
const startUnDownload = name => store.dispatch("startUnDownload", name);
|
||||
|
||||
const currentSelect = ref([0]);
|
||||
|
||||
@@ -106,6 +117,23 @@ const pluginDetail = computed(() => {
|
||||
return localPlugins.value[currentSelect.value] || {};
|
||||
});
|
||||
|
||||
const openPlugin = ({ cmd, code }) => {
|
||||
console.log(pluginDetail.value);
|
||||
window.rubick.openPlugin(
|
||||
JSON.parse(
|
||||
JSON.stringify({
|
||||
...pluginDetail.value,
|
||||
cmd,
|
||||
ext: {
|
||||
code,
|
||||
type: "text",
|
||||
payload: null
|
||||
}
|
||||
})
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const readme = computed(() => {
|
||||
if (!pluginDetail.value.name) return "";
|
||||
const readmePath = path.resolve(
|
||||
@@ -121,7 +149,7 @@ const readme = computed(() => {
|
||||
return "";
|
||||
});
|
||||
|
||||
const deletePlugin = async (plugin) => {
|
||||
const deletePlugin = async plugin => {
|
||||
startUnDownload(plugin.name);
|
||||
await window.market.deletePlugin(plugin);
|
||||
updateLocalPlugin();
|
||||
@@ -198,6 +226,15 @@ const deletePlugin = async (plugin) => {
|
||||
.desc-item {
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding: 10px 0;
|
||||
.ant-tag {
|
||||
margin-top: 6px;
|
||||
&.executable {
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
}
|
||||
.desc-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<template #actions>
|
||||
<a-button style="color: #ff4ea4;" type="text" :loading="item.isloading">
|
||||
<CloudDownloadOutlined
|
||||
v-show="!item.isloading && !item.isdwonload"
|
||||
v-show="!item.isloading && !item.isdownload"
|
||||
@click.stop="downloadPlugin(item, index)"
|
||||
style="font-size: 20px; cursor: pointer"
|
||||
/>
|
||||
@@ -57,9 +57,9 @@
|
||||
<div class="desc">
|
||||
{{ detail.description }}
|
||||
</div>
|
||||
<a-button v-if="!detail.isdwonload" @click.stop="downloadPlugin(detail)" shape="round" type="primary" :loading="detail.isloading">
|
||||
<a-button v-if="!detail.isdownload" @click.stop="downloadPlugin(detail)" shape="round" type="primary" :loading="detail.isloading">
|
||||
<template #icon>
|
||||
<CloudDownloadOutlined v-show="!detail.isloading && !detail.isdwonload" />
|
||||
<CloudDownloadOutlined v-show="!detail.isloading && !detail.isdownload" />
|
||||
</template>
|
||||
获取
|
||||
</a-button>
|
||||
|
||||
@@ -92,7 +92,8 @@ const totalPlugins = computed(() => store.state.totalPlugins);
|
||||
const { searchValue, current } = toRefs(state);
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
<style lang="less" scoped>
|
||||
@import '~@/assets/common.less';
|
||||
.market {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
@@ -101,26 +102,6 @@ const { searchValue, current } = toRefs(state);
|
||||
overflow: hidden;
|
||||
background: #F3EFEF;
|
||||
height: calc(~"100vh - 46px");
|
||||
.left-menu {
|
||||
width: 200px;
|
||||
height: 100vh;
|
||||
.search-container {
|
||||
padding: 10px;
|
||||
}
|
||||
.ant-input-affix-wrapper {
|
||||
border: none;
|
||||
}
|
||||
.ant-menu {
|
||||
background: #F3EFEF;
|
||||
.ant-menu-item-selected {
|
||||
background-color: #E2E2E2;
|
||||
color: #141414;
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.container {
|
||||
background: #fff;
|
||||
width: calc(~'100% - 200px');
|
||||
|
||||
@@ -25,18 +25,21 @@
|
||||
<div class="settings-detail">
|
||||
<div v-if="currentSelect[0] === 'normal'">
|
||||
<div class="setting-item">
|
||||
<div class="title">
|
||||
快捷键(需要使用 option/ctrl/shift/command 键修饰)
|
||||
</div>
|
||||
<div class="title">快捷键</div>
|
||||
<div class="settings-item-li">
|
||||
<div class="label">显示/隐藏快捷键</div>
|
||||
<div
|
||||
class="value"
|
||||
tabIndex="-1"
|
||||
@keyup="(e) => changeShortCut(e, 'showAndHidden')"
|
||||
>
|
||||
{{ shortCut.showAndHidden }}
|
||||
</div>
|
||||
<a-tooltip placement="top" trigger="click">
|
||||
<template #title>
|
||||
<span>{{ tipText }} </span>
|
||||
</template>
|
||||
<div
|
||||
class="value"
|
||||
tabIndex="-1"
|
||||
@keyup="e => changeShortCut(e, 'showAndHidden')"
|
||||
>
|
||||
{{ shortCut.showAndHidden }}
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
@@ -73,8 +76,8 @@
|
||||
<div>
|
||||
按下快捷键,自动搜索对应关键字,当关键字结果完全匹配,且结果唯一时,会直接指向该功能。
|
||||
</div>
|
||||
<h3 style="margin-top: 10px;">示例</h3>
|
||||
<a-divider style="margin: 5px 0;" />
|
||||
<h3 style="margin-top: 10px">示例</h3>
|
||||
<a-divider style="margin: 5px 0" />
|
||||
<a-list item-layout="horizontal" :data-source="examples">
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item>
|
||||
@@ -91,36 +94,41 @@
|
||||
<div class="feature-container">
|
||||
<div class="keywords item">
|
||||
<div>快捷键</div>
|
||||
<a-tooltip placement="top" trigger="click">
|
||||
<template #title>
|
||||
<span>先按功能键(Ctrl、Shift、Alt、Option、Command),再按其他普通键。或按
|
||||
F1-F12 单键
|
||||
</span>
|
||||
</template>
|
||||
<div
|
||||
:key="index"
|
||||
v-for="(item, index) in global"
|
||||
class="value"
|
||||
tabIndex="2"
|
||||
@keyup="(e) => changeGlobalKey(e, index)"
|
||||
>
|
||||
{{ item.key }}
|
||||
</div>
|
||||
</a-tooltip>
|
||||
<template :key="index" v-for="(item, index) in global">
|
||||
<a-tooltip placement="top" trigger="click">
|
||||
<template #title>
|
||||
<span>{{ tipText }}或按 F1-F12 单键 </span>
|
||||
</template>
|
||||
<div
|
||||
class="value"
|
||||
tabIndex="2"
|
||||
@keyup="e => changeGlobalKey(e, index)"
|
||||
>
|
||||
{{ item.key }}
|
||||
<MinusCircleOutlined
|
||||
@click.stop="deleteGlobalKey(e, index)"
|
||||
/>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</div>
|
||||
<div class="short-cut item">
|
||||
<div>功能关键字</div>
|
||||
<a-input
|
||||
:key="index"
|
||||
:value="item.value"
|
||||
v-for="(item, index) in global"
|
||||
class="value"
|
||||
:disabled="!item.key"
|
||||
@change="(e) => changeGlobalValue(index, e.target.value)"
|
||||
/>
|
||||
<template v-for="(item, index) in global" :key="index">
|
||||
<a-input
|
||||
:value="item.value"
|
||||
class="value"
|
||||
allowClear
|
||||
:disabled="!item.key"
|
||||
@change="e => changeGlobalValue(index, e.target.value)"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div @click="addConfig" class="add-global">+ 新增全局快捷功能</div>
|
||||
<div @click="addConfig" class="add-global">
|
||||
<PlusCircleOutlined />
|
||||
新增全局快捷功能
|
||||
</div>
|
||||
</div>
|
||||
<Localhost v-if="currentSelect[0] === 'localhost'" />
|
||||
</div>
|
||||
@@ -128,9 +136,15 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ToolOutlined, LaptopOutlined, DatabaseOutlined } from "@ant-design/icons-vue";
|
||||
import {
|
||||
ToolOutlined,
|
||||
LaptopOutlined,
|
||||
DatabaseOutlined,
|
||||
MinusCircleOutlined,
|
||||
PlusCircleOutlined
|
||||
} from "@ant-design/icons-vue";
|
||||
import debounce from "lodash.debounce";
|
||||
import { ref, reactive, watch, toRefs, toRaw } from "vue";
|
||||
import { ref, reactive, watch, toRefs, computed, toRaw } from "vue";
|
||||
import keycodes from "./keycode";
|
||||
import Localhost from "./localhost.vue";
|
||||
|
||||
@@ -139,24 +153,29 @@ const { remote, ipcRenderer } = window.require("electron");
|
||||
const examples = [
|
||||
{
|
||||
title: "快捷键 「 Alt + W」 关键字 「 微信」",
|
||||
desc: "按下Alt + W 直接打开本地微信应用",
|
||||
desc: "按下Alt + W 直接打开本地微信应用"
|
||||
},
|
||||
{
|
||||
title: "快捷键 「 Alt + Q」 关键字 「 取色」",
|
||||
desc: "按下Alt + Q 直接打开屏幕取色功能",
|
||||
},
|
||||
desc: "按下Alt + Q 直接打开屏幕取色功能"
|
||||
}
|
||||
];
|
||||
|
||||
const state = reactive({
|
||||
shortCut: {},
|
||||
common: {},
|
||||
local: {},
|
||||
global: [],
|
||||
global: []
|
||||
});
|
||||
|
||||
const tipText = computed(() => {
|
||||
const optionKeyName = window.rubick.isMacOs() ? "Option、Command" : "Alt";
|
||||
return `先按功能键(Ctrl、Shift、${optionKeyName}),再按其他普通键。`;
|
||||
});
|
||||
|
||||
const currentSelect = ref(["normal"]);
|
||||
|
||||
const {perf, global: defaultGlobal} = remote.getGlobal("OP_CONFIG").get();
|
||||
const { perf, global: defaultGlobal } = remote.getGlobal("OP_CONFIG").get();
|
||||
|
||||
state.shortCut = perf.shortCut;
|
||||
state.common = perf.common;
|
||||
@@ -164,14 +183,18 @@ state.local = perf.local;
|
||||
state.global = defaultGlobal;
|
||||
|
||||
const setConfig = debounce(() => {
|
||||
remote.getGlobal("OP_CONFIG").set(JSON.parse(JSON.stringify({
|
||||
perf: {
|
||||
shortCut: state.shortCut,
|
||||
common: state.common,
|
||||
local: state.local,
|
||||
},
|
||||
global: state.global,
|
||||
})));
|
||||
remote.getGlobal("OP_CONFIG").set(
|
||||
JSON.parse(
|
||||
JSON.stringify({
|
||||
perf: {
|
||||
shortCut: state.shortCut,
|
||||
common: state.common,
|
||||
local: state.local
|
||||
},
|
||||
global: state.global
|
||||
})
|
||||
)
|
||||
);
|
||||
ipcRenderer.send("re-register");
|
||||
}, 2000);
|
||||
|
||||
@@ -184,15 +207,15 @@ const changeShortCut = (e, key) => {
|
||||
}
|
||||
if (e.ctrlKey && e.keyCode !== 17) {
|
||||
const compose = `Ctrl+${keycodes[e.keyCode].toUpperCase()}`;
|
||||
state.perf.shortCut[key] = compose;
|
||||
state.shortCut[key] = compose;
|
||||
}
|
||||
if (e.shiftKey && e.keyCode !== 16) {
|
||||
const compose = `Shift+${keycodes[e.keyCode].toUpperCase()}`;
|
||||
state.perf.shortCut[key] = compose;
|
||||
state.shortCut[key] = compose;
|
||||
}
|
||||
if (e.metaKey && e.keyCode !== 93) {
|
||||
const compose = `Command+${keycodes[e.keyCode].toUpperCase()}`;
|
||||
state.perf.shortCut[key] = compose;
|
||||
state.shortCut[key] = compose;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -224,19 +247,25 @@ const changeGlobalKey = (e, index) => {
|
||||
|
||||
const changeGlobalValue = (index, value) => {
|
||||
state.global[index].value = value;
|
||||
}
|
||||
};
|
||||
|
||||
const deleteGlobalKey = (e, index) => {
|
||||
state.global.splice(index, 1);
|
||||
// delete state.global[index];
|
||||
};
|
||||
|
||||
const addConfig = () => {
|
||||
state.global.push({
|
||||
key: "",
|
||||
value: "",
|
||||
value: ""
|
||||
});
|
||||
};
|
||||
|
||||
const {shortCut, common, local, global} = toRefs(state);
|
||||
const { shortCut, common, local, global } = toRefs(state);
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
<style lang="less" scoped>
|
||||
@import "~@/assets/common.less";
|
||||
.settings {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
@@ -244,26 +273,6 @@ const {shortCut, common, local, global} = toRefs(state);
|
||||
background: #f3efef;
|
||||
height: calc(~"100vh - 46px");
|
||||
display: flex;
|
||||
.left-menu {
|
||||
width: 200px;
|
||||
height: 100%;
|
||||
.search-container {
|
||||
padding: 10px;
|
||||
}
|
||||
.ant-input-affix-wrapper {
|
||||
border: none;
|
||||
}
|
||||
.ant-menu {
|
||||
background: #F3EFEF;
|
||||
.ant-menu-item-selected {
|
||||
background-color: #E2E2E2;
|
||||
color: #141414;
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.settings-detail {
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
@@ -323,6 +332,26 @@ const {shortCut, common, local, global} = toRefs(state);
|
||||
height: 24px;
|
||||
font-weight: lighter;
|
||||
margin-top: 10px;
|
||||
position: relative;
|
||||
:deep(.ant-input) {
|
||||
color: #6c9fe2;
|
||||
font-weight: lighter;
|
||||
}
|
||||
&.ant-input-affix-wrapper {
|
||||
display: flex;
|
||||
}
|
||||
&:hover {
|
||||
.anticon {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.anticon {
|
||||
position: absolute;
|
||||
display: none;
|
||||
right: 4px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
.add-global {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
</a-form-item>
|
||||
<a-form-item has-feedback label="database url" name="database">
|
||||
<a-input
|
||||
placeholder="https://gitee.com/monkeyWang/rubick-database/raw/master"
|
||||
placeholder="https://gitcode.net/rubickcenter/rubick-database/-/raw/master"
|
||||
v-model:value="formState.database"
|
||||
/>
|
||||
</a-form-item>
|
||||
@@ -43,7 +43,7 @@ let _rev: any;
|
||||
|
||||
let defaultConfig = {
|
||||
register: "https://registry.npm.taobao.org",
|
||||
database: "https://gitee.com/monkeyWang/rubick-database/raw/master",
|
||||
database: "https://gitcode.net/rubickcenter/rubick-database/-/raw/master",
|
||||
access_token: "",
|
||||
};
|
||||
|
||||
@@ -69,7 +69,7 @@ const layout = {
|
||||
const resetForm = () => {
|
||||
formState.value = {
|
||||
register: "https://registry.npm.taobao.org",
|
||||
database: "https://gitee.com/monkeyWang/rubick-database/raw/master",
|
||||
database: "https://gitcode.net/rubickcenter/rubick-database/-/raw/master",
|
||||
access_token: "",
|
||||
};
|
||||
};
|
||||
|
||||
9469
feature/yarn.lock
Normal file
9469
feature/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "rubick",
|
||||
"version": "2.0.1-beta.19",
|
||||
"version": "2.0.4-beta.1",
|
||||
"author": "muwoo <2424880409@qq.com>",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -3,7 +3,7 @@
|
||||
"pluginName": "rubick 系统菜单",
|
||||
"description": "rubick 系统菜单",
|
||||
"main": "index.html",
|
||||
"logo": "https://static.91jkys.com/upload/202112/08/8a1abbb051bf4b05bbc9bbf66ade63f2.png",
|
||||
"logo": "https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/acb761082f4a4b46847e7cd8b180f63c~tplv-k3u1fbpfcp-watermark.image",
|
||||
"version": "0.0.0",
|
||||
"preload":"preload.js",
|
||||
"pluginType": "ui",
|
||||
|
||||
@@ -4,7 +4,7 @@ const os = require("os");
|
||||
const ipcSendSync = (type, data) => {
|
||||
const returnValue = ipcRenderer.sendSync("msg-trigger", {
|
||||
type,
|
||||
data,
|
||||
data
|
||||
});
|
||||
if (returnValue instanceof Error) throw returnValue;
|
||||
return returnValue;
|
||||
@@ -13,7 +13,7 @@ const ipcSendSync = (type, data) => {
|
||||
const ipcSend = (type, data) => {
|
||||
ipcRenderer.send("msg-trigger", {
|
||||
type,
|
||||
data,
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
@@ -30,7 +30,9 @@ window.rubick = {
|
||||
onPluginOut(cb) {
|
||||
typeof cb === "function" && (window.rubick.hooks.onPluginOut = cb);
|
||||
},
|
||||
|
||||
openPlugin(plugin) {
|
||||
ipcSendSync("loadPlugin", plugin);
|
||||
},
|
||||
// 窗口交互
|
||||
hideMainWindow() {
|
||||
ipcSendSync("hideMainWindow");
|
||||
@@ -49,7 +51,7 @@ window.rubick = {
|
||||
(window.rubick.hooks.onSubInputChange = onChange);
|
||||
ipcSendSync("setSubInput", {
|
||||
placeholder,
|
||||
isFocus,
|
||||
isFocus
|
||||
});
|
||||
},
|
||||
removeSubInput() {
|
||||
@@ -74,15 +76,15 @@ window.rubick = {
|
||||
copyText(text) {
|
||||
return ipcSendSync("copyText", { text });
|
||||
},
|
||||
copyFile: (file) => {
|
||||
return ipcSendSync("copyFile", { file })
|
||||
copyFile: file => {
|
||||
return ipcSendSync("copyFile", { file });
|
||||
},
|
||||
db: {
|
||||
put: (data) => ipcSendSync("dbPut", { data }),
|
||||
get: (id) => ipcSendSync("dbGet", { id }),
|
||||
remove: (doc) => ipcSendSync("dbRemove", { doc }),
|
||||
bulkDocs: (docs) => ipcSendSync("dbBulkDocs", { docs }),
|
||||
allDocs: (key) => ipcSendSync("dbAllDocs", { key }),
|
||||
put: data => ipcSendSync("dbPut", { data }),
|
||||
get: id => ipcSendSync("dbGet", { id }),
|
||||
remove: doc => ipcSendSync("dbRemove", { doc }),
|
||||
bulkDocs: docs => ipcSendSync("dbBulkDocs", { docs }),
|
||||
allDocs: key => ipcSendSync("dbAllDocs", { key })
|
||||
},
|
||||
dbStorage: {
|
||||
setItem: (key, value) => {
|
||||
@@ -93,14 +95,14 @@ window.rubick = {
|
||||
const res = ipcSendSync("dbPut", { data: target });
|
||||
if (res.error) throw new Error(res.message);
|
||||
},
|
||||
getItem: (key) => {
|
||||
getItem: key => {
|
||||
const res = ipcSendSync("dbGet", { id: key });
|
||||
return res && "value" in res ? res.value : null;
|
||||
},
|
||||
removeItem: (key) => {
|
||||
removeItem: key => {
|
||||
const res = ipcSendSync("dbGet", { id: key });
|
||||
res && ipcSendSync("dbRemove", { doc: res });
|
||||
},
|
||||
}
|
||||
},
|
||||
isDarkColors() {
|
||||
return false;
|
||||
@@ -141,4 +143,16 @@ window.rubick = {
|
||||
removePlugin() {
|
||||
ipcSend("removePlugin");
|
||||
},
|
||||
|
||||
shellShowItemInFolder: path => {
|
||||
ipcSend("shellShowItemInFolder", { path });
|
||||
},
|
||||
|
||||
redirect: (label, payload) => {
|
||||
// todo
|
||||
},
|
||||
|
||||
shellBeep: () => {
|
||||
ipcSend("shellBeep")
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
|
||||
export default (): string => {
|
||||
let localDataFile: any = process.env.HOME;
|
||||
if (!localDataFile) {
|
||||
localDataFile = process.env.LOCALAPPDATA;
|
||||
}
|
||||
return localDataFile;
|
||||
const rubickPath = path.join(localDataFile, "rubick")
|
||||
if (!fs.existsSync(rubickPath)) {
|
||||
fs.mkdirSync(rubickPath);
|
||||
}
|
||||
return rubickPath;
|
||||
};
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import appSearch from "@/core/app-search";
|
||||
import PluginHandler from "@/core/plugin-handler";
|
||||
import LocalDb from "@/core/db";
|
||||
|
||||
export {
|
||||
appSearch,
|
||||
PluginHandler,
|
||||
LocalDb,
|
||||
};
|
||||
|
||||
@@ -3,9 +3,11 @@ import path from "path";
|
||||
import commonConst from "../../common/utils/commonConst";
|
||||
import { PLUGIN_INSTALL_DIR as baseDir } from "@/common/constans/main";
|
||||
|
||||
const getRelativePath = (indexPath) => {
|
||||
return commonConst.windows() ? indexPath.replace("file://", "") : indexPath.replace("file:", "");
|
||||
}
|
||||
const getRelativePath = indexPath => {
|
||||
return commonConst.windows()
|
||||
? indexPath.replace("file://", "")
|
||||
: indexPath.replace("file:", "");
|
||||
};
|
||||
|
||||
const getPreloadPath = (plugin, pluginIndexPath) => {
|
||||
const { name, preload, tplPath, indexPath } = plugin;
|
||||
@@ -54,8 +56,8 @@ export default () => {
|
||||
devTools: true,
|
||||
webviewTag: true,
|
||||
preload,
|
||||
session: ses,
|
||||
},
|
||||
session: ses
|
||||
}
|
||||
});
|
||||
window.setBrowserView(view);
|
||||
view.webContents.loadURL(pluginIndexPath);
|
||||
@@ -67,6 +69,25 @@ export default () => {
|
||||
executeHooks("PluginReady", plugin.ext);
|
||||
window.webContents.executeJavaScript(`window.pluginLoaded()`);
|
||||
});
|
||||
// 修复请求跨域问题
|
||||
view.webContents.session.webRequest.onBeforeSendHeaders(
|
||||
(details, callback) => {
|
||||
callback({
|
||||
requestHeaders: { referer: "*", ...details.requestHeaders }
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
view.webContents.session.webRequest.onHeadersReceived(
|
||||
(details, callback) => {
|
||||
callback({
|
||||
responseHeaders: {
|
||||
"Access-Control-Allow-Origin": ["*"],
|
||||
...details.responseHeaders
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const removeView = (window: BrowserWindow) => {
|
||||
@@ -95,6 +116,6 @@ export default () => {
|
||||
init,
|
||||
getView,
|
||||
removeView,
|
||||
executeHooks,
|
||||
executeHooks
|
||||
};
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
Notification,
|
||||
nativeImage,
|
||||
clipboard,
|
||||
shell
|
||||
} from "electron";
|
||||
import { runner, detach } from "../browsers";
|
||||
import fs from "fs";
|
||||
@@ -36,7 +37,15 @@ export const API: any = {
|
||||
return;
|
||||
}
|
||||
},
|
||||
openPlugin({ plugin }, window) {
|
||||
|
||||
loadPlugin({ data: plugin }, window) {
|
||||
window.webContents.executeJavaScript(
|
||||
`window.loadPlugin(${JSON.stringify(plugin)})`
|
||||
);
|
||||
API.openPlugin({ data: plugin }, window);
|
||||
},
|
||||
|
||||
openPlugin({ data: plugin }, window) {
|
||||
if (API.currentPlugin && API.currentPlugin.name === plugin.name) return;
|
||||
window.setSize(window.getSize()[0], 60);
|
||||
runnerInstance.removeView(window);
|
||||
@@ -44,7 +53,7 @@ export const API: any = {
|
||||
API.currentPlugin = plugin;
|
||||
window.webContents.executeJavaScript(
|
||||
`window.setCurrentPlugin(${JSON.stringify({
|
||||
currentPlugin: API.currentPlugin,
|
||||
currentPlugin: API.currentPlugin
|
||||
})})`
|
||||
);
|
||||
window.show();
|
||||
@@ -85,7 +94,7 @@ export const API: any = {
|
||||
if (!originWindow) return;
|
||||
originWindow.webContents.executeJavaScript(
|
||||
`window.setSubInput(${JSON.stringify({
|
||||
placeholder: data.placeholder,
|
||||
placeholder: data.placeholder
|
||||
})})`
|
||||
);
|
||||
},
|
||||
@@ -105,7 +114,7 @@ export const API: any = {
|
||||
if (!originWindow) return;
|
||||
originWindow.webContents.executeJavaScript(
|
||||
`window.setSubInputValue(${JSON.stringify({
|
||||
value: data.text,
|
||||
value: data.text
|
||||
})})`
|
||||
);
|
||||
},
|
||||
@@ -120,7 +129,7 @@ export const API: any = {
|
||||
const notify = new Notification({
|
||||
title: plugin.pluginName,
|
||||
body,
|
||||
icon: plugin.logo,
|
||||
icon: plugin.logo
|
||||
});
|
||||
notify.show();
|
||||
},
|
||||
@@ -155,7 +164,7 @@ export const API: any = {
|
||||
return dbInstance.bulkDocs(API.DBKEY, data.docs);
|
||||
},
|
||||
dbAllDocs({ data }) {
|
||||
return dbInstance.bulkDocs(API.DBKEY, data.key);
|
||||
return dbInstance.allDocs(API.DBKEY, data.key);
|
||||
},
|
||||
getFeatures() {
|
||||
return API.currentPlugin.features;
|
||||
@@ -165,7 +174,7 @@ export const API: any = {
|
||||
...API.currentPlugin,
|
||||
features: (() => {
|
||||
let has = false;
|
||||
API.currentPlugin.features.some((feature) => {
|
||||
API.currentPlugin.features.some(feature => {
|
||||
has = feature.code === data.feature.code;
|
||||
return has;
|
||||
});
|
||||
@@ -173,11 +182,11 @@ export const API: any = {
|
||||
return [...API.currentPlugin.features, data.feature];
|
||||
}
|
||||
return API.currentPlugin.features;
|
||||
})(),
|
||||
})()
|
||||
};
|
||||
window.webContents.executeJavaScript(
|
||||
`window.updatePlugin(${JSON.stringify({
|
||||
currentPlugin: API.currentPlugin,
|
||||
currentPlugin: API.currentPlugin
|
||||
})})`
|
||||
);
|
||||
return true;
|
||||
@@ -185,16 +194,16 @@ export const API: any = {
|
||||
removeFeature({ data }, window) {
|
||||
API.currentPlugin = {
|
||||
...API.currentPlugin,
|
||||
features: API.currentPlugin.features.filter((feature) => {
|
||||
features: API.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: API.currentPlugin,
|
||||
currentPlugin: API.currentPlugin
|
||||
})})`
|
||||
);
|
||||
return true;
|
||||
@@ -206,12 +215,12 @@ export const API: any = {
|
||||
runnerInstance.getView().webContents.sendInputEvent({
|
||||
type: "keyDown",
|
||||
modifiers,
|
||||
keyCode: code,
|
||||
keyCode: code
|
||||
});
|
||||
} else {
|
||||
runnerInstance.getView().webContents.sendInputEvent({
|
||||
type: "keyDown",
|
||||
keyCode: code,
|
||||
keyCode: code
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -222,11 +231,11 @@ export const API: any = {
|
||||
window.setBrowserView(null);
|
||||
window.webContents
|
||||
.executeJavaScript(`window.getMainInputInfo()`)
|
||||
.then((res) => {
|
||||
.then(res => {
|
||||
detachInstance.init(
|
||||
{
|
||||
...API.currentPlugin,
|
||||
subInput: res,
|
||||
subInput: res
|
||||
},
|
||||
window.getBounds(),
|
||||
view
|
||||
@@ -239,13 +248,26 @@ export const API: any = {
|
||||
detachInputChange({ data }) {
|
||||
API.sendSubInputChangeEvent({ data });
|
||||
},
|
||||
|
||||
getLocalId() {
|
||||
return encodeURIComponent(app.getPath("home"));
|
||||
},
|
||||
|
||||
shellShowItemInFolder({ data }) {
|
||||
shell.showItemInFolder(data.path);
|
||||
return true;
|
||||
},
|
||||
|
||||
shellBeep() {
|
||||
shell.beep();
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
export default (mainWindow: BrowserWindow) => {
|
||||
// 响应 preload.js 事件
|
||||
ipcMain.on("msg-trigger", async (event, arg) => {
|
||||
const window = arg.winId ? BrowserWindow.fromId(arg.winId) : mainWindow;
|
||||
|
||||
const data = await API[arg.type](arg, window, event);
|
||||
event.returnValue = data;
|
||||
// event.sender.send(`msg-back-${arg.type}`, data);
|
||||
|
||||
@@ -18,7 +18,13 @@ function createTray(window: BrowserWindow): Promise<Tray> {
|
||||
icon = "./icons/icon@2x.png";
|
||||
}
|
||||
const appIcon = new Tray(path.join(__static, icon));
|
||||
const contextMenu = Menu.buildFromTemplate([
|
||||
|
||||
const getShowAndHiddenHotKey = (): string => {
|
||||
const config = global.OP_CONFIG.get();
|
||||
return config.perf.shortCut.showAndHidden;
|
||||
}
|
||||
|
||||
const createContextMenu = () => Menu.buildFromTemplate([
|
||||
{
|
||||
label: "帮助文档",
|
||||
click: () => {
|
||||
@@ -38,7 +44,7 @@ function createTray(window: BrowserWindow): Promise<Tray> {
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: "显示窗口",
|
||||
accelerator: "Alt+R",
|
||||
accelerator: getShowAndHiddenHotKey(),
|
||||
click() {
|
||||
window.show();
|
||||
},
|
||||
@@ -67,9 +73,10 @@ function createTray(window: BrowserWindow): Promise<Tray> {
|
||||
},
|
||||
]);
|
||||
appIcon.on("click", () => {
|
||||
appIcon.popUpContextMenu(contextMenu);
|
||||
appIcon.setContextMenu(createContextMenu());
|
||||
appIcon.popUpContextMenu();
|
||||
});
|
||||
appIcon.setContextMenu(contextMenu);
|
||||
appIcon.setContextMenu(createContextMenu());
|
||||
|
||||
resolve(appIcon);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div v-if="commonConst.windows()" class="drag-bar"></div>
|
||||
<div :class="!commonConst.windows() && 'drag'" id="components-layout">
|
||||
<div v-if="commonConst.windows() || commonConst.linux()" class="drag-bar"></div>
|
||||
<div :class="!commonConst.windows() && !commonConst.linux() && 'drag'" id="components-layout">
|
||||
<div class="rubick-select">
|
||||
<Search
|
||||
:currentPlugin="currentPlugin"
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
<template>
|
||||
<div class="rubick-select">
|
||||
<div class="select-tag" v-show="currentPlugin.cmd">{{ currentPlugin.cmd }}</div>
|
||||
<div :class="clipboardFile[0].name ? 'clipboard-tag' : 'clipboard-img'" v-if="!!clipboardFile.length">
|
||||
<div
|
||||
:class="clipboardFile[0].name ? 'clipboard-tag' : 'clipboard-img'"
|
||||
v-if="!!clipboardFile.length"
|
||||
>
|
||||
<img :src="getIcon()" />
|
||||
<div class="ellipse">{{ clipboardFile[0].name }}</div>
|
||||
<a-tag color="#aaa" v-if="clipboardFile.length > 1">{{ clipboardFile.length }}</a-tag>
|
||||
@@ -10,20 +13,18 @@
|
||||
id="search"
|
||||
class="main-input"
|
||||
@input="(e) => changeValue(e)"
|
||||
@keydown.down="(e) => keydownEvent(e, 1)"
|
||||
@keydown.up="(e) => keydownEvent(e, -1)"
|
||||
@keydown.down="(e) => keydownEvent(e, 'down')"
|
||||
@keydown.up="(e) => keydownEvent(e, 'up')"
|
||||
@keydown="e => checkNeedInit(e)"
|
||||
:value="searchValue"
|
||||
:placeholder="placeholder || 'Hi, Rubick2'"
|
||||
@keypress.enter="(e) => keydownEvent(e)"
|
||||
@keypress.enter="(e) => keydownEvent(e, 'enter')"
|
||||
@keypress.space="(e) => keydownEvent(e, 'space')"
|
||||
@focus="emit('focus')"
|
||||
>
|
||||
<template #suffix>
|
||||
<div class="suffix-tool" >
|
||||
<MoreOutlined
|
||||
@click="showSeparate()"
|
||||
class="icon-more"
|
||||
/>
|
||||
<div class="suffix-tool">
|
||||
<MoreOutlined @click="showSeparate()" class="icon-more" />
|
||||
<div v-if="currentPlugin && currentPlugin.logo" style="position: relative">
|
||||
<a-spin v-show="pluginLoading" class="loading">
|
||||
<template #indicator>
|
||||
@@ -81,7 +82,7 @@ const emit = defineEmits([
|
||||
"readClipboardContent",
|
||||
]);
|
||||
|
||||
const keydownEvent = (e, index) => {
|
||||
const keydownEvent = (e, key: string) => {
|
||||
const { ctrlKey, shiftKey, altKey, metaKey } = e;
|
||||
const modifiers: Array<string> = [];
|
||||
ctrlKey && modifiers.push("control");
|
||||
@@ -95,10 +96,24 @@ const keydownEvent = (e, index) => {
|
||||
modifiers,
|
||||
},
|
||||
});
|
||||
if(index) {
|
||||
emit("changeCurrent", index);
|
||||
} else {
|
||||
!props.currentPlugin.name && emit("choosePlugin");
|
||||
const runPluginDisable = e.target.value === "" || props.currentPlugin.name
|
||||
switch (key) {
|
||||
case "up":
|
||||
emit("changeCurrent", -1);
|
||||
break;
|
||||
case "down":
|
||||
emit("changeCurrent", 1);
|
||||
break;
|
||||
case "enter":
|
||||
if (runPluginDisable) return;
|
||||
emit("choosePlugin");
|
||||
break;
|
||||
case "space":
|
||||
if (runPluginDisable || !opConfig.get().perf.common.space) return;
|
||||
emit("choosePlugin");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -225,13 +240,16 @@ const newWindow = () => {
|
||||
border: none;
|
||||
outline: none;
|
||||
box-shadow: none !important;
|
||||
.ant-select-selection, .ant-input, .ant-select-selection__rendered {
|
||||
.ant-select-selection,
|
||||
.ant-input,
|
||||
.ant-select-selection__rendered {
|
||||
height: 100% !important;
|
||||
font-size: 22px;
|
||||
border: none !important;
|
||||
}
|
||||
}
|
||||
.rubick-logo, .icon-tool {
|
||||
.rubick-logo,
|
||||
.icon-tool {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: #574778;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { reactive, toRefs, ref } from "vue";
|
||||
import { nativeImage, remote, ipcRenderer } from "electron";
|
||||
import { appSearch, PluginHandler } from "@/core";
|
||||
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";
|
||||
@@ -10,7 +11,7 @@ import { PLUGIN_INSTALL_DIR as baseDir } from "@/common/constans/renderer";
|
||||
|
||||
const createPluginManager = (): any => {
|
||||
const pluginInstance = new PluginHandler({
|
||||
baseDir,
|
||||
baseDir
|
||||
});
|
||||
|
||||
const state: any = reactive({
|
||||
@@ -18,7 +19,7 @@ const createPluginManager = (): any => {
|
||||
plugins: [],
|
||||
localPlugins: [],
|
||||
currentPlugin: {},
|
||||
pluginLoading: false,
|
||||
pluginLoading: false
|
||||
});
|
||||
|
||||
const appList = ref([]);
|
||||
@@ -27,25 +28,29 @@ const createPluginManager = (): any => {
|
||||
appList.value = await appSearch(nativeImage);
|
||||
};
|
||||
|
||||
const openPlugin = (plugin) => {
|
||||
const loadPlugin = plugin => {
|
||||
state.pluginLoading = true;
|
||||
state.currentPlugin = plugin;
|
||||
};
|
||||
|
||||
const openPlugin = plugin => {
|
||||
if (plugin.pluginType === "ui" || plugin.pluginType === "system") {
|
||||
if (state.currentPlugin && state.currentPlugin.name === plugin.name) {
|
||||
return;
|
||||
}
|
||||
state.pluginLoading = true;
|
||||
state.currentPlugin = plugin;
|
||||
loadPlugin(plugin);
|
||||
ipcRenderer.sendSync("msg-trigger", {
|
||||
type: "openPlugin",
|
||||
plugin: JSON.parse(
|
||||
data: JSON.parse(
|
||||
JSON.stringify({
|
||||
...plugin,
|
||||
ext: plugin.ext || {
|
||||
code: plugin.feature.code,
|
||||
type: plugin.cmd.type || "text",
|
||||
payload: null,
|
||||
},
|
||||
payload: null
|
||||
}
|
||||
})
|
||||
),
|
||||
)
|
||||
});
|
||||
setSearchValue("");
|
||||
}
|
||||
@@ -56,13 +61,18 @@ const createPluginManager = (): any => {
|
||||
|
||||
const { searchValue, onSearch, setSearchValue, placeholder } =
|
||||
searchManager();
|
||||
const { options, searchFocus, clipboardFile, clearClipboardFile, readClipboardContent } =
|
||||
optionsManager({
|
||||
searchValue,
|
||||
appList,
|
||||
openPlugin,
|
||||
currentPlugin: toRefs(state).currentPlugin,
|
||||
});
|
||||
const {
|
||||
options,
|
||||
searchFocus,
|
||||
clipboardFile,
|
||||
clearClipboardFile,
|
||||
readClipboardContent
|
||||
} = optionsManager({
|
||||
searchValue,
|
||||
appList,
|
||||
openPlugin,
|
||||
currentPlugin: toRefs(state).currentPlugin
|
||||
});
|
||||
// plugin operation
|
||||
const getPluginInfo = async ({ pluginName, pluginPath }) => {
|
||||
const pluginInfo = await pluginInstance.getAdapterInfo(
|
||||
@@ -74,11 +84,11 @@ const createPluginManager = (): any => {
|
||||
icon: pluginInfo.logo,
|
||||
indexPath: commonConst.dev()
|
||||
? "http://localhost:8081/#/"
|
||||
: `file://${path.join(pluginPath, "../", pluginInfo.main)}`,
|
||||
: `file://${path.join(pluginPath, "../", pluginInfo.main)}`
|
||||
};
|
||||
};
|
||||
|
||||
const changeSelect = (select) => {
|
||||
const changeSelect = select => {
|
||||
state.currentPlugin = select;
|
||||
};
|
||||
|
||||
@@ -89,6 +99,9 @@ const createPluginManager = (): any => {
|
||||
const removePlugin = (plugin: any) => {
|
||||
// todo
|
||||
};
|
||||
|
||||
window.loadPlugin = plugin => loadPlugin(plugin);
|
||||
|
||||
window.updatePlugin = ({ currentPlugin }: any) => {
|
||||
state.currentPlugin = currentPlugin;
|
||||
remote.getGlobal("LOCAL_PLUGINS").updatePlugin(currentPlugin);
|
||||
@@ -124,7 +137,7 @@ const createPluginManager = (): any => {
|
||||
searchFocus,
|
||||
clipboardFile,
|
||||
clearClipboardFile,
|
||||
readClipboardContent,
|
||||
readClipboardContent
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
17
src/renderer/shims-vue.d.ts
vendored
17
src/renderer/shims-vue.d.ts
vendored
@@ -1,22 +1,23 @@
|
||||
/* eslint-disable */
|
||||
declare module '*.vue' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
declare module "*.vue" {
|
||||
import type { DefineComponent } from "vue";
|
||||
const component: DefineComponent<{}, {}, any>;
|
||||
export default component;
|
||||
}
|
||||
|
||||
declare module 'main' {
|
||||
export function main (): any
|
||||
declare module "main" {
|
||||
export function main(): any;
|
||||
}
|
||||
|
||||
declare const __static: string
|
||||
declare const __static: string;
|
||||
|
||||
declare module 'lodash.throttle'
|
||||
declare module "lodash.throttle";
|
||||
|
||||
interface Window {
|
||||
setSubInput: ({ placeholder }: { placeholder: string }) => void;
|
||||
setSubInputValue: ({ value }: { value: string }) => void;
|
||||
removeSubInput: () => void;
|
||||
loadPlugin: (plugin: any) => void;
|
||||
updatePlugin: (plugin: any) => void;
|
||||
initRubick: () => void;
|
||||
setCurrentPlugin: (plugin: any) => void;
|
||||
|
||||
@@ -51,7 +51,10 @@ module.exports = {
|
||||
},
|
||||
mac: {
|
||||
icon: "public/icons/icon.icns",
|
||||
target: "pkg",
|
||||
target: [
|
||||
"dmg",
|
||||
"pkg"
|
||||
],
|
||||
extendInfo: {
|
||||
LSUIElement: 1,
|
||||
},
|
||||
@@ -67,6 +70,7 @@ module.exports = {
|
||||
linux: {
|
||||
icon: "public/icons/",
|
||||
publish: ["github"],
|
||||
target: "deb",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user