Compare commits

...

88 Commits

Author SHA1 Message Date
muwoo
a546bc0d59
Update package.json 2025-07-25 18:40:09 +08:00
muwoo
c732e448c3
Merge pull request #449 from siriusol/master
fix #448
2025-07-25 18:39:43 +08:00
Ther
fbc7da0606 fix #448 2025-07-25 18:24:52 +08:00
muwoo
6315ec12ae
Update main.yml 2025-07-24 14:13:59 +08:00
muwoo
3ba8250d7c
Update package.json 2025-07-24 14:12:18 +08:00
muwoo
706aa84374
Merge pull request #432 from magicedy/fix-key-conflicts
fix: resolve key conflicts between local-start-app and plugin-history
2025-07-24 14:11:24 +08:00
muwoo
f70bf3983e
Merge pull request #444 from lanxiuyun/ctrl+ctrl
Double click the modifer to pop up window
2025-07-24 14:10:09 +08:00
muwoo
47359308fc
Update package.json 2025-07-17 20:56:32 +08:00
muwoo
3f03e5578e
Merge pull request #438 from siriusol/master
fix issues #437
2025-07-17 20:56:14 +08:00
lanxiuyun
7cabbe26f5 删除提示重启文本 2025-06-12 15:09:38 +08:00
lanxiuyun
5c048c6341 优化代码可读性 2025-06-12 15:08:37 +08:00
lanxiuyun
e90a30c8a4 优化 uIOhook 逻辑 2025-06-12 15:04:10 +08:00
lanxiuyun
599538db76 Update package.json 2025-06-10 14:33:16 +08:00
lanxiuyun
e9c41b6bdb Update index.vue 2025-06-10 14:23:51 +08:00
lanxiuyun
1e7a8209b7 支持双击快捷键 2025-06-10 14:14:37 +08:00
lanxiuyun
481cd44ab3 Update registerHotKey.ts 2025-06-10 10:53:13 +08:00
lanxiuyun
d41caa742b Update index.vue 2025-06-10 10:39:44 +08:00
lanxiuyun
69218a728b Update index.vue 2025-06-10 10:25:25 +08:00
Ther
73cef1512c fix #437 2025-05-24 19:42:18 +08:00
magicedy
986ad42ed7 fix: resolve key conflicts between local-start-app and plugin-history 2025-04-27 12:14:32 +08:00
muwoo
42aec3403a
Merge pull request #415 from yangyangdaji/readme
readme: some fix
2025-03-04 16:45:10 +08:00
yangyangdaji
8c15dba68d
readme (en) some fix
1. fix blue line between badges in github
2. change badges tooltip

Signed-off-by: yangyangdaji <1504305527@qq.com>
2025-02-27 11:55:26 +08:00
yangyangdaji
37647de7a8
readme (zh-cn) 一些修复
1. 修复一些徽章在 github 浏览时出现的蓝色蓝点
2. 修复徽章一些徽章的提示名称

Signed-off-by: yangyangdaji <1504305527@qq.com>
2025-02-27 11:51:04 +08:00
muwoo
1b2c9b3577
Merge pull request #411 from PineSongCN/master
🐛 修复 #410
2025-01-21 16:53:24 +08:00
muwoo
7cb832829d
Update README.md 2025-01-21 16:52:19 +08:00
徐松
02da06c450 Update package.json version @4.3.2 2025-01-21 16:46:41 +08:00
徐松
e613fc19d4 🐛 修复 修改database url已过期源为https://gitee.com/monkeyWang/rubickdatabase/raw/master 2025-01-21 16:45:05 +08:00
徐松
c7807aeb3f 🐛 修复 https://github.com/rubickCenter/rubick/issues/410\#issuecomment-2601278762 2025-01-20 15:46:19 +08:00
muwoo
9813573679
Update package.json 2024-12-26 18:40:45 +08:00
muwoo
61ec18f0dc
fix: #404 2024-12-26 18:40:27 +08:00
wangwei1240
5ca1ba1271 feat: 为了更好的安装体验,切换到依赖本地 node 环境 2024-12-11 20:06:21 +08:00
wangwei1240
8c3186afef Merge remote-tracking branch 'origin/master' 2024-12-11 20:05:20 +08:00
wangwei1240
de0e9ed8f2 fix: 更新版本 2024-12-11 20:05:00 +08:00
muwoo
ef85084730
Update package.json 2024-10-05 18:41:32 +08:00
muwoo
b4b7c81b60
Update index.ts 2024-10-05 18:41:16 +08:00
muwoo
4b79cce2f4
Update package.json 2024-09-30 21:19:07 +08:00
muwoo
ae10dac5f7
Merge pull request #396 from clevertension/master
fix #395: the plugin windows error with data retrieve
2024-09-30 21:18:23 +08:00
clevertension
1e0babe22d fix #395: the plugin windows error data retrieve 2024-09-30 15:22:13 +08:00
muwoo
5ec18caa72
Update package.json 2024-09-29 09:55:52 +08:00
muwoo
b7d8932291
Update index.ts
ref: 调整插件市场的数据源
2024-09-29 09:55:37 +08:00
muwoo
5608a147f7
Update package.json 2024-08-06 18:16:14 +08:00
muwoo
132fb94289
Update main.ts 2024-08-06 18:15:49 +08:00
muwoo
bb1a74b3b9
Update main.yml 2024-07-19 13:49:22 +08:00
layyback
bf9da854c7 release new version 2024-07-18 19:24:32 +08:00
layyback
a2c5bcc90c add new keyboard events 2024-07-18 18:58:34 +08:00
layyback
b9f4333c01 🎨 fix text display issue 2024-07-18 18:47:52 +08:00
layyback
bbeddb3fe6 support #371 2024-07-18 17:53:23 +08:00
layyback
4a2ca33e02 support #371 2024-07-18 17:52:20 +08:00
layyback
0578c7c7eb 🔨 fix #377 2024-07-18 17:41:30 +08:00
layyback
ef34452a4f 🔨 fix #377 2024-07-18 17:40:03 +08:00
layyback
286d9da8d1 🐛 fix hooks triggering issue 2024-07-18 17:25:11 +08:00
layyback
6b9d5182bf 🐛 fix hooks triggering issue 2024-07-18 16:46:33 +08:00
muwoo
2053491782
Update README.md 2024-06-14 19:49:24 +08:00
muwoo
e128d01b81
Merge pull request #184 from qidian99/master
Fix regex match error
2024-06-12 13:52:04 +08:00
木偶
c3bc0bdb9e
fix: #352 2024-05-28 20:13:10 +08:00
木偶
f1f4e62177
fix: #352 2024-05-28 20:12:38 +08:00
wangwei1240
c07d4bae55 fix: 更新版本 2024-05-16 20:14:41 +08:00
wangwei1240
c78dd9c4b6 fix: 修复 #364 2024-05-16 20:13:45 +08:00
muwoo
2dd4ed10cc 💚 修复构建报错:https://github.com/electron/electron/issues/41089 2024-02-20 18:16:42 +08:00
muwoo
70ce3dd037 🐛 修复 #338, #345, #340 2024-02-20 18:07:19 +08:00
muwoo
a0644c0ccf 🐛 fix #333, fix #327 2023-12-27 11:34:55 +08:00
muwoo
583e9934fa icon 替换 2023-11-18 13:49:35 +08:00
muwoo
7e66b3f3e9 linux 构建包修复 2023-11-16 15:54:58 +08:00
muwoo
342f0f36a5 linux 构建包修复 2023-11-16 15:38:06 +08:00
muwoo
2a75e440ad linux 构建包修复 2023-11-16 15:25:33 +08:00
muwoo
11f53d1e07 linux 构建包修复 2023-11-16 15:19:37 +08:00
muwoo
beb8134539 linux 构建包修复 2023-11-16 15:03:50 +08:00
muwoo
d916525934 支持 asar gz 包发布 2023-11-15 11:07:20 +08:00
muwoo
7d4ccb83a2 尝试单独构建 asar 包 2023-11-14 18:17:47 +08:00
muwoo
36c2a714b5 尝试单独构建 asar 包 2023-11-14 18:11:15 +08:00
muwoo
696c24657b 尝试单独构建 asar 包 #300 2023-11-14 18:08:59 +08:00
muwoo
f59069b2ec 尝试单独构建 asar 包 #300 2023-11-14 18:07:22 +08:00
muwoo
0c16139313 尝试单独构建 asar 包 #300 2023-11-14 17:33:14 +08:00
muwoo
c99ec18151 尝试单独构建 asar 包 #300 2023-11-14 17:13:15 +08:00
muwoo
dcea66e848 尝试单独构建 asar 包 #300 2023-11-14 16:52:08 +08:00
muwoo
75e3111587 📝 Writing docs. 2023-11-14 11:41:36 +08:00
muwoo
bd1757e068 📝 Writing docs. 2023-11-14 11:37:53 +08:00
muwoo
2055bf61b1 🐛 修复插件市场插件详情页点击下载无反应的bug 2023-11-13 14:15:04 +08:00
muwoo
6c096fcd99 ♻️ 优化搜索内容排序,修复setSubInput 无法触发 inputChange bug 2023-11-13 11:40:35 +08:00
muwoo
1656418c10 🐛 fix #289,#291,#290 2023-11-10 15:00:26 +08:00
muwoo
f671b83b6a 🐛 fix #289,#291,#290 2023-11-10 14:35:37 +08:00
muwoo
dfb8446cfd 🐛 windows 启动bug 2023-11-03 13:59:29 +08:00
muwoo
4e59294b16 🐛 修复超级面板设置bug 2023-11-03 11:28:38 +08:00
muwoo
562a13fdff 支持网页快开插件 2023-11-02 16:00:50 +08:00
muwoo
9663232864 🐛 修复销毁 BrowserView 的bug 2023-11-01 15:30:08 +08:00
muwoo
3f7285b177 🐛 fix #278, #277 2023-10-31 12:20:24 +08:00
muwoo
e8c8f40bae 🐛 fix #278, #277 2023-10-31 12:19:35 +08:00
Dian Qi
472879f9b2 Fix format regex error that will match all inputs 2023-06-04 20:30:06 +08:00
84 changed files with 896 additions and 9908 deletions

View File

@ -23,10 +23,14 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [macos-11, windows-2019, ubuntu-latest]
os: [macos-latest, windows-2022, ubuntu-latest]
# create steps
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: '3.10'
# step1: check out repository
- name: Check out git repository
uses: actions/checkout@v2
@ -42,6 +46,7 @@ jobs:
run: |
sudo apt-get install libxtst-dev libpng++-dev
sudo apt-get install --no-install-recommends -y icnsutils graphicsmagick xz-utils
sudo snap install snapcraft --classic
# step3: yarn
- name: Yarn install
run: |

3
.gitignore vendored
View File

@ -1,6 +1,7 @@
.DS_Store
node_modules
/build
build/*
!build/icons
# local env files

2
.npmrc
View File

@ -1 +1 @@
electron_mirror=https://npm.taobao.org/mirrors/electron/
electron_mirror=https://npmmirror.com/mirrors/electron/

104
README.md
View File

@ -1,46 +1,41 @@
English | [简体中文](./README.zh-CN.md)
<div align= "center">
<img align="center" width=200 src="https://user-images.githubusercontent.com/21073039/128333805-73e086f0-5523-46a3-a096-cba80b904c46.png" />
<img align="center" width=200 src="./public/logo.png" />
</div>
<div align= "center">
<h1>Rubick</h1>
<img alt="release" src="https://img.shields.io/github/downloads/rubickCenter/rubick/total" />
<a href="https://github.com/rubickCenter/rubick/releases">
<img alt="release" src="https://img.shields.io/github/package-json/v/rubickCenter/rubick" />
</a>
<a href="https://github.com/rubickCenter/rubick/actions">
<img alt=building src=https://img.shields.io/github/actions/workflow/status/rubickCenter/rubick/main.yml>
</a>
<a href="https://github.com/rubickCenter/rubick/blob/master/LICENSE">
<img alt="npm" src="https://img.shields.io/github/license/rubickCenter/rubick" />
</a>
<a href="https://github.com/rubickCenter/rubick/stargazers">
<img alt="star" src="https://img.shields.io/github/stars/rubickCenter/rubick?style=social">
</a>
<a href="https://gitee.com/monkeyWang/rubick">
<img alt="码云" src="https://img.shields.io/badge/Gitee--yellow.svg?style=social&logo=data:image/svg+xml;base64,PHN2ZyB0PSIxNTc0ODM3MTM4ODM3IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjE3NzAiICAgICB3aWR0aD0iMTYiIGhlaWdodD0iMTYiPiAgICA8cGF0aCBkPSJNODkxIDQyOC44SDQ2NS44Yy0yMC40IDAtMzcgMTYuNS0zNyAzN3Y5Mi40YzAgMjAuNCAxNi41IDM3IDM3IDM3aDI1OC45YzIwLjQgMCAzNyAxNi42IDM3IDM3djE4LjRjMCA2MS4zLTQ5LjcgMTEwLjktMTEwLjkgMTEwLjlIMjk5LjRjLTIwLjQgMC0zNy0xNi42LTM3LTM3VjM3My4yYzAtNjEuMyA0OS43LTExMC45IDExMC45LTExMC45aDUxNy42YzIwLjQgMCAzNy0xNi41IDM3LTM3bDAuMS05Mi4zYzAtMjAuNC0xNi41LTM3LTM3LTM3SDM3My4zQzIyMC4yIDk2IDk2IDIyMC4yIDk2IDM3My4zVjg5MWMwIDIwLjQgMTYuNiAzNyAzNyAzN2g1NDUuNEM4MTYuMiA5MjggOTI4IDgxNi4zIDkyOCA2NzguNFY0NjUuOGMwLTIwLjQtMTYuNi0zNy0zNy0zN3oiICAgICAgICAgIGZpbGw9IiNkODFlMDYiIHAtaWQ9IjE3NzEiPjwvcGF0aD48L3N2Zz4="/>
</a>
<div align="center">
<h1>Rubick</h1>
<img alt="downloads" src="https://img.shields.io/github/downloads/rubickCenter/rubick/total" />
<a href="https://github.com/rubickCenter/rubick/releases"><img alt="latest release" src="https://img.shields.io/github/package-json/v/rubickCenter/rubick" /></a>
<a href="https://github.com/rubickCenter/rubick/actions"><img alt="github action building" src="https://img.shields.io/github/actions/workflow/status/rubickCenter/rubick/main.yml" /></a>
<a href="https://github.com/rubickCenter/rubick/blob/master/LICENSE"><img alt="license" src="https://img.shields.io/github/license/rubickCenter/rubick" /></a>
<a href="https://github.com/rubickCenter/rubick/stargazers"><img alt="github stars" src="https://img.shields.io/github/stars/rubickCenter/rubick?style=social" /></a>
<a href="https://gitee.com/monkeyWang/rubick"><img alt="gitee mirror" src="https://img.shields.io/badge/Gitee--yellow.svg?style=social&logo=data:image/svg+xml;base64,PHN2ZyB0PSIxNTc0ODM3MTM4ODM3IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjE3NzAiICAgICB3aWR0aD0iMTYiIGhlaWdodD0iMTYiPiAgICA8cGF0aCBkPSJNODkxIDQyOC44SDQ2NS44Yy0yMC40IDAtMzcgMTYuNS0zNyAzN3Y5Mi40YzAgMjAuNCAxNi41IDM3IDM3IDM3aDI1OC45YzIwLjQgMCAzNyAxNi42IDM3IDM3djE4LjRjMCA2MS4zLTQ5LjcgMTEwLjktMTEwLjkgMTEwLjlIMjk5LjRjLTIwLjQgMC0zNy0xNi42LTM3LTM3VjM3My4yYzAtNjEuMyA0OS43LTExMC45IDExMC45LTExMC45aDUxNy42YzIwLjQgMCAzNy0xNi41IDM3LTM3bDAuMS05Mi4zYzAtMjAuNC0xNi41LTM3LTM3LTM3SDM3My4zQzIyMC4yIDk2IDk2IDIyMC4yIDk2IDM3My4zVjg5MWMwIDIwLjQgMTYuNiAzNyAzNyAzN2g1NDUuNEM4MTYuMiA5MjggOTI4IDgxNi4zIDkyOCA2NzguNFY0NjUuOGMwLTIwLjQtMTYuNi0zNy0zNy0zN3oiICAgICAgICAgIGZpbGw9IiNkODFlMDYiIHAtaWQ9IjE3NzEiPjwvcGF0aD48L3N2Zz4=" /></a>
</div>
An open-source toolbox based on Electron, freely integrating rich plugins to create the ultimate desktop productivity tool. Rubick is one of the heroes in Dota, whose core skill is the ability to use the skills of other heroes through plugins, and then move on. This aligns perfectly with the design philosophy of this tool, which is why it is named Rubick.
<div align= "center">
<img align="center" src="https://picx.zhimg.com/80/v2-f8fe09ef125dac5fdcbef3fe00f92b21_720w.png" />
</div>
Open-source plugin-based desktop efficiency toolbox. The plugins are installed and uninstalled based on npm, which is very lightweight. The plugin data supports webdav multi-terminal synchronization, which is very secure. It supports internal network deployment and can be customized for further development, which is very flexible.
## Sponsor
我们通过有偿的方式积累高质量的常见问题、最佳实践文档,加入星球后可以和作者进行互动和答疑。我们提供技术支持、答疑解惑、定制化插件开发、二次定制化开发 rubick 等等官方服务。
权益明细可以参考文档:[权益明细](https://rubickcenter.github.io/rubick/super/)
<img width=400 src=https://picx.zhimg.com/80/v2-6deabf65175d18080439ef813102d18c_720w.png />
## Installation package
## Get Rubick
Download the latest release:
* [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)
## Docs
[Rubick website](https://rubick.vip)
[Rubick Docs](https://rubickCenter.github.io/docs/)
## How To Use Rubick
After installing rubick, you can quickly launch the main program by pressing the shortcut keys Alt/Option+R. Entering keywords in the main program input box can search for corresponding apps, plugins, files...
Select the ones you want and use them.
If you don't want the function, you can click the logo on the left to enter the plugin market and find the ones you want to install.
## Feature list
- [x] Plugin management based on the npm package pattern, installing plugins is as simple as installing npm packages.
@ -50,13 +45,6 @@ An open-source toolbox based on Electron, freely integrating rich plugins to cre
- [x] Supports enterprise-level intranet deployment.
- [x] Supports multiple languages.
## Docs
[Rubick website](https://rubick.vip)
[Rubick Docs](https://rubickCenter.github.io/rubick/)
## Core functionality showcase.
### 1. Search system application
Support pinyin and abbreviations to search system applications
@ -81,17 +69,43 @@ In "Rubick," search for "Preferences," go to "Account and Settings," and then se
![](https://pic1.zhimg.com/80/v2-ff85793741e4dff82a729d3eb3d41551_720w.png)
### More features
If you need more features, please come here to give us suggestions[issues](https://github.com/rubickCenter/rubick/issues) 。
We will add valuable ideas to the later development. At the same time, welcome to join and build together。
## Related Repositories
## 贡献
This project exists thanks to all the people who contribute. [[Contribute](https://github.com/rubickCenter/rubick/graphs/contributors)]. <a href="https://github.com/rubickCenter/rubick/graphs/contributors"><img src="https://opencollective.com/rubick/contributors.svg?width=890&button=false" /></a>
[Rubick Plugins Repositories](https://gitee.com/rubick-center)
## 反馈
对本项目有兴趣或者想要交流学习的同学可以扫码加下面的微信,备注 rubick帮助我们更好的成长
[Rubick Plugins Database](https://gitcode.net/rubickcenter/rubick-database)
[Rubick Plugin CLI](https://github.com/rubickCenter/rubick-plugin-cli)
## Sponsor
### 1. Join the Knowledge Planet
We have accumulated a lot of knowledge and common issues about rubick on the Knowledge Planet. You can pay to join our knowledge community to discuss with us. We will answer at any time!
<img width=400 src=https://picx.zhimg.com/80/v2-6deabf65175d18080439ef813102d18c_720w.png />
### 2. Buy me a cup of coffee
If the project is helpful to you, you can buy me a cup of coffee as a reward!
<div align= "left">
<img width="180" src="https://picx.zhimg.com/80/v2-911d249dc454f3460451a4e1ecceeb14_720w.png">
<img width="180" src="https://picx.zhimg.com/80/v2-3160247d6099053405e6cd2cb6afb5e5_720w.png">
</div>
## 友情链接
<a href="https://pro.kuaitu.cc/" target="_blank">
<img width="100" src="https://github.com/user-attachments/assets/6127488e-466b-4e71-98ab-00fb3c76553e" />
</a>
## Feedback
Those who are interested in this project or want to exchange and learn can scan the QR code and add the following WeChat, with the comment rubick, to help us grow better.
![image](https://user-images.githubusercontent.com/21073039/127327603-9796f246-ee4b-4950-a69d-ce3205ec9569.png)
<a href="https://hellogithub.com/repository/0a3e2484b44e481e9dcf1850e45193cd" target="_blank"><img src="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=0a3e2484b44e481e9dcf1850e45193cd&claim_uid=vXGwjpmYNsBex0C" alt="FeaturedHelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" /></a>
## Contribute
This project exists thanks to all the people who contribute. [[Contribute](https://github.com/rubickCenter/rubick/graphs/contributors)]. <a href="https://github.com/rubickCenter/rubick/graphs/contributors"><img src="https://opencollective.com/rubick/contributors.svg?width=890&button=false" /></a>
## License
This project is licensed under the MIT License - see the [LICENSE](https://github.com/rubickCenter/rubick/blob/master/LICENSE) file for details.

View File

@ -2,46 +2,42 @@
<div align= "center">
<img align="center" width=200 src="https://user-images.githubusercontent.com/21073039/128333805-73e086f0-5523-46a3-a096-cba80b904c46.png" />
<img align="center" width=200 src="./public/logo.png" />
</div>
<div align="center">
<h1>Rubick</h1>
<img alt="累计下载数" src="https://img.shields.io/github/downloads/rubickCenter/rubick/total" />
<a href="https://github.com/rubickCenter/rubick/releases"><img alt="最新发布版本" src="https://img.shields.io/github/package-json/v/rubickCenter/rubick" /></a>
<a href="https://github.com/rubickCenter/rubick/actions"><img alt="github action 构建" src="https://img.shields.io/github/actions/workflow/status/rubickCenter/rubick/main.yml" /></a>
<a href="https://github.com/rubickCenter/rubick/blob/master/LICENSE"><img alt="许可证" src="https://img.shields.io/github/license/rubickCenter/rubick" /></a>
<a href="https://github.com/rubickCenter/rubick/stargazers"><img alt="github 收藏数" src="https://img.shields.io/github/stars/rubickCenter/rubick?style=social" /></a>
<a href="https://gitee.com/monkeyWang/rubick"><img alt="gitee 镜像源" src="https://img.shields.io/badge/Gitee--yellow.svg?style=social&logo=data:image/svg+xml;base64,PHN2ZyB0PSIxNTc0ODM3MTM4ODM3IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjE3NzAiICAgICB3aWR0aD0iMTYiIGhlaWdodD0iMTYiPiAgICA8cGF0aCBkPSJNODkxIDQyOC44SDQ2NS44Yy0yMC40IDAtMzcgMTYuNS0zNyAzN3Y5Mi40YzAgMjAuNCAxNi41IDM3IDM3IDM3aDI1OC45YzIwLjQgMCAzNyAxNi42IDM3IDM3djE4LjRjMCA2MS4zLTQ5LjcgMTEwLjktMTEwLjkgMTEwLjlIMjk5LjRjLTIwLjQgMC0zNy0xNi42LTM3LTM3VjM3My4yYzAtNjEuMyA0OS43LTExMC45IDExMC45LTExMC45aDUxNy42YzIwLjQgMCAzNy0xNi41IDM3LTM3bDAuMS05Mi4zYzAtMjAuNC0xNi41LTM3LTM3LTM3SDM3My4zQzIyMC4yIDk2IDk2IDIyMC4yIDk2IDM3My4zVjg5MWMwIDIwLjQgMTYuNiAzNyAzNyAzN2g1NDUuNEM4MTYuMiA5MjggOTI4IDgxNi4zIDkyOCA2NzguNFY0NjUuOGMwLTIwLjQtMTYuNi0zNy0zNy0zN3oiICAgICAgICAgIGZpbGw9IiNkODFlMDYiIHAtaWQ9IjE3NzEiPjwvcGF0aD48L3N2Zz4=" /></a>
</div>
<div align= "center">
<h1>Rubick</h1>
<img alt="release" src="https://img.shields.io/github/downloads/rubickCenter/rubick/total" />
<a href="https://github.com/rubickCenter/rubick/releases">
<img alt="release" src="https://img.shields.io/github/package-json/v/rubickCenter/rubick" />
</a>
<a href="https://github.com/rubickCenter/rubick/actions">
<img alt=building src=https://img.shields.io/github/workflow/status/rubickCenter/rubick/Build>
</a>
<a href="https://github.com/rubickCenter/rubick/blob/master/LICENSE">
<img alt="npm" src="https://img.shields.io/github/license/rubickCenter/rubick" />
</a>
<a href="https://github.com/rubickCenter/rubick/stargazers">
<img alt="star" src="https://img.shields.io/github/stars/rubickCenter/rubick?style=social">
</a>
<a href="https://gitee.com/monkeyWang/rubick">
<img alt="码云" src="https://img.shields.io/badge/Gitee--yellow.svg?style=social&logo=data:image/svg+xml;base64,PHN2ZyB0PSIxNTc0ODM3MTM4ODM3IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjE3NzAiICAgICB3aWR0aD0iMTYiIGhlaWdodD0iMTYiPiAgICA8cGF0aCBkPSJNODkxIDQyOC44SDQ2NS44Yy0yMC40IDAtMzcgMTYuNS0zNyAzN3Y5Mi40YzAgMjAuNCAxNi41IDM3IDM3IDM3aDI1OC45YzIwLjQgMCAzNyAxNi42IDM3IDM3djE4LjRjMCA2MS4zLTQ5LjcgMTEwLjktMTEwLjkgMTEwLjlIMjk5LjRjLTIwLjQgMC0zNy0xNi42LTM3LTM3VjM3My4yYzAtNjEuMyA0OS43LTExMC45IDExMC45LTExMC45aDUxNy42YzIwLjQgMCAzNy0xNi41IDM3LTM3bDAuMS05Mi4zYzAtMjAuNC0xNi41LTM3LTM3LTM3SDM3My4zQzIyMC4yIDk2IDk2IDIyMC4yIDk2IDM3My4zVjg5MWMwIDIwLjQgMTYuNiAzNyAzNyAzN2g1NDUuNEM4MTYuMiA5MjggOTI4IDgxNi4zIDkyOCA2NzguNFY0NjUuOGMwLTIwLjQtMTYuNi0zNy0zNy0zN3oiICAgICAgICAgIGZpbGw9IiNkODFlMDYiIHAtaWQ9IjE3NzEiPjwvcGF0aD48L3N2Zz4="/>
</a>
<img align="center" src="https://picx.zhimg.com/80/v2-f8fe09ef125dac5fdcbef3fe00f92b21_720w.png" />
</div>
开源的插件化桌面端效率工具箱。插件是基于 npm 进行安装和卸载,非常轻便。插件数据支持 webdav 多端同步,非常安全。支持内网部署,可二次定制化开发,非常灵活。
基于 electron 的开源工具箱自由集成丰富插件打造极致的桌面端效能工具。Rubick(拉比克) 是 dota 里面的英雄之一,其核心技能是插件化使用其他英雄的技能,用完即走。非常符合本工具的设计理念,所以取名 Rubick。
## 获取 rubick
下载最新的安装包:
## 赞助和服务
我们通过有偿的方式积累高质量的常见问题、最佳实践文档,加入星球后可以和作者进行互动和答疑。我们提供技术支持、答疑解惑、定制化插件开发、二次定制化开发 rubick 等等官方服务。
权益明细可以参考文档:[权益明细](https://rubickcenter.github.io/rubick/super/)
<img width=400 src=https://picx.zhimg.com/80/v2-6deabf65175d18080439ef813102d18c_720w.png />
## 安装包
* [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)
## 使用文档
[Rubick 官网](https://rubick.vip)
[Rubick Docs](https://rubickCenter.github.io/rubick/)
## 如何使用 rubick
安装完成 rubick 后,可以通过快捷键 Alt/Option+R 可以快速呼起主程序。主程序输入框内输入关键词可以搜索出对应的 App、插件、文件... 选择即可使用。如果没有想要的功能,可以点击左侧的 logo 进入插件市场寻找自己想要的插件进行安装。
## 支持能力
- [x] 基于 npm 包模式的插件管理,安装插件和安装 npm 包一样简单
- [x] 支持 webdav 多端数据同步,真正的数据安全同步
@ -50,12 +46,6 @@
- [x] 支持企业化内网部署
- [x] 支持多语言
## 使用文档
[Rubick 官网](https://rubick.vip)
[Rubick Docs](https://rubickCenter.github.io/rubick/)
## 核心功能展示
### 1. 搜索系统应用
@ -81,18 +71,36 @@
![](https://pic1.zhimg.com/80/v2-ff85793741e4dff82a729d3eb3d41551_720w.png)
### 更多功能
如果您还需要更多功能,欢迎来这里给我们提建议:[issues](https://github.com/rubickCenter/rubick/issues) 。
有价值的想法我们会加入到后期的开发当中。同时也欢迎一起加入共建。
## 关联仓库
## 贡献
This project exists thanks to all the people who contribute. [[Contribute](https://github.com/rubickCenter/rubick/graphs/contributors)]. <a href="https://github.com/rubickCenter/rubick/graphs/contributors"><img src="https://opencollective.com/rubick/contributors.svg?width=890&button=false" /></a>
[Rubick 插件仓库](https://gitee.com/rubick-center)
[Rubick 插件数据库](https://gitcode.net/rubickcenter/rubick-database)
[Rubick Plugin CLI](https://github.com/rubickCenter/rubick-plugin-cli)
## 赞助
### 1. 加入知识星球
我们在知识星球积累了大量的关于 rubick 的知识和常见问题,您可以付费加入我们的知识星球来一起讨论。我们将随时解答!
<img width=400 src=https://picx.zhimg.com/80/v2-6deabf65175d18080439ef813102d18c_720w.png />
### 2. 打赏喝杯咖啡
如果项目对你有帮助,可以请我喝杯咖啡赞赏!
<div align= "left">
<img width="180" src="https://picx.zhimg.com/80/v2-911d249dc454f3460451a4e1ecceeb14_720w.png">
<img width="180" src="https://picx.zhimg.com/80/v2-3160247d6099053405e6cd2cb6afb5e5_720w.png">
</div>
## 反馈
对本项目有兴趣或者想要交流学习的同学可以扫码加下面的微信,备注 rubick帮助我们更好的成长
![image](https://user-images.githubusercontent.com/21073039/127327603-9796f246-ee4b-4950-a69d-ce3205ec9569.png)
## 贡献
This project exists thanks to all the people who contribute. [[Contribute](https://github.com/rubickCenter/rubick/graphs/contributors)]. <a href="https://github.com/rubickCenter/rubick/graphs/contributors"><img src="https://opencollective.com/rubick/contributors.svg?width=890&button=false" /></a>
## License
This project is licensed under the MIT License - see the [LICENSE](https://github.com/rubickCenter/rubick/blob/master/LICENSE) file for details.

View File

@ -1,24 +0,0 @@
#!/usr/bin/env sh
# 确保脚本抛出遇到的错误
set -e
# 生成静态文件
cd docs && npm run docs:build
# 进入生成的文件夹
cd docs/.vuepress/dist
# 如果是发布到自定义域名
# echo 'www.example.com' > CNAME
git init
git add -A
git commit -m 'deploy'
# 如果发布到 https://<USERNAME>.github.io
# git push -f git@github.com:<USERNAME>/<USERNAME>.github.io.git master
# 如果发布到 https://<USERNAME>.github.io/<REPO>
git push -f git@github.com:rubickCenter/rubick.git master:gh-pages
cd -

View File

@ -5864,7 +5864,7 @@ lodash.memoize@^4.1.2:
lodash.throttle@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
resolved "https://registry.npmmirror.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==
lodash.transform@^4.6.0:

View File

@ -1,50 +0,0 @@
module.exports = {
title: 'Rubick',
description: '你的开源桌面插件应用',
base: '/rubick/',
themeConfig: {
themeColor: {
blue: "#2196f3",
red: "#2196f3",
green: "#2196f3",
orange: "#2196f3",
},
logo: '/images/logo.png',
nav: [
{ text: '使用文档', link: '/guide/' },
{ text: '开发者', link: '/dev/' },
],
sidebar: [
{
title: '使用文档', // 必要的
path: '/guide/', // 可选的, 标题的跳转链接,应为绝对路径且必须存在
sidebarDepth: 1, // 可选的, 默认值是 1
},
{
title: '插件开发',
path: '/dev/',
},
{
title: '特殊服务',
path: '/super/',
},
{
title: 'API',
path: '/api/',
},
{
title: '贡献 rubick',
path: '/run/',
}
],
// 假定是 GitHub. 同时也可以是一个完整的 GitLab URL
repo: 'https://github.com/rubickCenter/rubick',
// 自定义仓库链接文字。默认从 `themeConfig.repo` 中自动推断为
// "GitHub"/"GitLab"/"Bitbucket" 其中之一,或是 "Source"。
repoLabel: 'Github',
// 默认是 false, 设置为 true 来启用
editLinks: true,
// 默认为 "Edit this page"
editLinkText: '帮助我们改善此页面!'
}
}

@ -1 +0,0 @@
Subproject commit 7b52f0fb4a06d8036a35e125368cf2ddd67dbaa8

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

View File

@ -1,7 +0,0 @@
$accentColor = #ff4ea4//
$codeBgColor = #282c34//
//f12class
.sidebar-group.is-sub-group > .sidebar-heading:not(.clickable){
opacity :1
}

View File

@ -1,16 +0,0 @@
---
home: true
heroImage: /images/logo.png
heroText: Rubick
tagline: 基于 Electron 开源的插件化工具箱
actionText: 快速上手 →
actionLink: /guide/
features:
- title: 极其轻量
details: rubick 仅仅包含插件运行所需要的API本身不内置任何插件可以看成是 electron 的二次封装框架。
- title: 更强大的插件能力
details: 不仅仅支持ui插件需要搜索呼起使用还支持系统插件不需要搜索只要rubick在运行系统插件即可用
- title: 更便捷的插件管理
details: rubick 插件全部托管在 npm 仓库rubick 插件的安装、使用、删除就是 npm 包的安装、使用、删除
footer: MIT Licensed | Copyright (c) 2021 muwoo
---

View File

@ -1,261 +0,0 @@
## 事件
### onPluginReady(callback)、onPluginEnter(callback)
* `callback` Function
`callback` 内会返回一个 `object` 对象,来描述进入当前插件的环境信息:
* `code` String
> plugin.json 配置的 feature.code
* `type` String
> plugin.json 配置的 feature.cmd.type可以为 "text"、"img"、 "files"、 "regex"、 "over"、"window"
* payload String | Object | Array
> feature.cmd.type 对应匹配的数据
当插件装载成功rubick 将会主动调用这个方法, 所有的 `api` 都应该在 `onPluginReady` 之后进行调用。
#### 示例
```js
rubick.onPluginReady(({ code, type, payload }) => {
console.log('插件装配完成,已准备好')
})
/*
type 为 "files" 时, payload 值示例
[
{
"isFile": true,
"isDirectory": false,
"name": "demo.js",
"path": "C:\\demo.js"
}
]
type 为 "img" 时, payload 值示例
data:image/png;base64,...
type 为 "text"、"regex"、 "over" 时, payload 值为进入插件时的主输入框文本
*/
```
### onPluginOut(callback)
* `callback` Function
每当插件从前台进入到后台时rubick 将会主动调用这个方法。
## 窗口交互
### hideMainWindow()
隐藏主窗口
### showMainWindow()
显示主窗口
### setExpendHeight(height)
执行该方法将会修改插件窗口的高度。
* `height` Integer
* 返回 `Boolean`
#### 示例
```js
rubick.setExpendHeight(100)
```
### setSubInput(onChange, placeholder)
设置插件输入框监听,当进入插件后,用户搜索会触发`onChange` 函数
* `onChange` Function
* `Object`
* `text` String
> 子输入框文本修改时触发
* `placeholder` String (可选)
> 子输入框占位符
* `isFocus` Boolean (可选)
> 子输入框是否获得焦点,默认 true
`返回 Boolean`
#### 示例
```js
rubick.setSubInput(({ text }) => {
console.log(text)
}, '搜索')
```
### setSubInputValue(value)
直接对子输入框的值进行设置。
* `value` String
* `返回` Boolean
#### 示例
```js
rubick.setSubInputValue('rubick')
```
## 系统
### showNotification(body)
显示系统通知
* `body` String
```js
rubick.showNotification('Hi, rubick')
```
### shellOpenPath(fullPath)
打开给定路径的文件
* `fullPath` String
```js
rubick.shellOpenPath('/path/file')
```
### shellOpenExternal(url)
浏览器打开URL
* `url` String
```js
rubick.shellOpenExternal('https://www.baidu.com')
```
### getPath(name)
electron 内置 getPath 能力,详见 [electron API](https://www.electronjs.org/docs/latest/api/app#appgetpathname)
```js
console.log(rubick.getPath('cache'));
```
## 本地数据库
`rubick db` 是基于开源的 [pouchdb](https://github.com/pouchdb/pouchdb) 封装的
### rubick.db.put(doc)
* `doc` Object
* `返回` Object
#### 示例
```js
// 创建请求
rubick.db.put({
_id: "demo",
data: "demo"
})
// 返回 {id: "demo", ok: true, rev: "1-05c9b92e6f24287dc1f4ec79d9a34fa8"}
// 更新请求
rubick.db.put({
_id: "demo",
data: "demo",
_rev: "1-05c9b92e6f24287dc1f4ec79d9a34fa8"
})
```
_id 代表这个文档在数据库中唯一值,如果值不存在,则会创建一个新的文档,如果值已经存在,则会进行更新。你可能已经注意到,返回对象中包含一个 rev
属性,这是代表此文档的版本,每次对文档进行更新时,都要带上最新的版本号,否则更新将失败,版本化的意义在于解决同步时数据冲突。
另外需要注意,每次更新时都要传入完整的文档数据,无法对单个字段进行更新。
### rubick.db.get(id)
执行该方法将会根据文档 ID 获取数据
* `id` String
* `返回` Object
```js
rubick.db.get("demo")
// 返回 {_id: "demo", _rev: "3-9836c5c68af5aef618e17d615882942a", data: "demo"}
```
### rubick.db.remove(doc)
* `doc` String | Object
* `返回` Object 执行该方法将会删除数据库文档,可以传入文档对象或文档 id 进行操作。
```js
rubick.db.remove("demo")
// 返回 {id: "demo", ok: true, rev: "2-effe5dbc23dffc180d8411b23f3108fb"}
```
### rubick.db.bulkDocs(docs)
* `docs` Array
* `返回` Array 执行该方法将会批量更新数据库文档,传入需要更改的文档对象合并成数组进行批量更新。
```js
rubick.db.bulkDocs([{
_id: "demo1",
data: "demo",
_rev: "1-c8817a74e292eda4cba1a45924853af6"
}, {
_id: "demo2",
data: "demo",
_rev: "1-f0399b42cc6123a9cc8503632ba7b3a7"
}])
/* 返回
[{
id: "demo1", ok: true, rev: "2-7857b2801bc0303d2cc0bb82e8afd796"
}, {
id: "demo2", ok: true, rev: "2-7857b2801bc0303d2cc0bb82e8afd796"
}]
*/
```
### rubick.db.allDocs(key)
* `key` String | Array
* `返回` Array 执行该方法将会获取所有数据库文档,如果传入字符串,则会返回以字符串开头的文档,也可以传入指定 ID 的数组,不传入则为获取所有文档。
```js
// 获取所有文档
rubick.db.allDocs()
// 传入字符串则返回id以 demo 开头的文档
rubick.db.allDocs("demo")
/* 返回
[{
_id: "demo/123", _rev: "2-7857b2801bc0303d2cc0bb82e8afd796", data: "demo"
}, {
_id: "demo/124", _rev: "1-f0399b42cc6123a9cc8503632ba7b3a7", data: "demo"
}, {
_id: "demo/125", _rev: "1-f0399b42cc6123a9cc8503632ba7b3a7", data: "demo"
}]
*/
// 根据id数组请求
rubick.db.allDocs([
"demo1",
"demo2"
])
/* 返回
[{
_id: "demo1", _rev: "2-7857b2801bc0303d2cc0bb82e8afd796", data: "demo"
}, {
_id: "demo2", _rev: "1-f0399b42cc6123a9cc8503632ba7b3a7", data: "demo"
}]
*/
```

View File

@ -1,176 +0,0 @@
## 插件说明
`rubick` 插件分为 `UI插件``系统插件` 2类。下面分别介绍这 2 类插件的区别和作用。
1. UI 插件 <Badge type="tip" text="最常用" />:都会有 UI 界面,用于和用户交互,且需要通过关键词搜索选择进行使用,比如 `斗图` 插件,有界面展示,且需要再搜索框内搜索关键词选择后进行呼起才能使用。
2. 系统插件:可能不会有 UI 界面,在 `rubick` 启动的时候,会注册执行系统插件。比如`超级面板` 插件,安装完成后,即可在 `rubick` 运行时随时使用,不需要任何关键词和匹配。
## 开发 UI 插件
一个最基础插件的目录是这样的:
```
rubick-plugin-demo
|-- index.html
|-- package.json
|-- preload.js
```
### 文件说明
#### package.json
用于指定插件最基础的配置,一个最基础的配置信息如下:
```json
{
"name": "rubick-ui-plugin-demo",
"pluginName": "插件demo",
"description": "rubick ui 插件demo",
"author": "muwoo",
"main": "index.html",
"logo": "https://www.img/demo.png",
"version": "0.0.1",
"preload":"preload.js",
"homePage": "https://gitee.com/rubick-center/rubick-ui-plugin-demo/raw/master/README.md",
"pluginType": "ui",
"features": [
{
"code": "index",
"explain": "测试插件",
"cmds":[
"demo",
"测试"
]
}
]
}
```
核心字段说明:
* name 插件 `npm` 包名称,<Badge type="tip" text="必填" />
* pluginName 插件显示名称,用于展示给使用者 <Badge type="tip" text="必填" />
* description 插件描述,描述这个插件的作用 <Badge type="tip" text="必填" />
* author 插件作者
* main 入口文件,一般为 `index.html`
* logo 尺寸建议 200 * 200, 插件的 logo, 需要是 http/https 在线地址不支持本地logo <Badge type="tip" text="必填" />
* version 插件的版本 <Badge type="tip" text="必填" />
* preload 预加载脚本
* homePage: 插件 readme raw 地址
* pluginType: 插件类型枚举ui, system. 当前选 ui <Badge type="tip" text="必填" />
* features 插件核心功能列表 <Badge type="tip" text="必填" />
* features.code 插件某个功能的识别码,可用于区分不同的功能 <Badge type="tip" text="必填" />
* features.explain 插件某个功能的解释 <Badge type="tip" text="必填" />
* features.cmds 输入框内搜索该 cmd 进入插件 <Badge type="tip" text="必填" />
#### index.html
插件的入口文件,用于展示插件的样式,一个最基础的 `html` 结构可以是这样:
```html
<!DOCTYPE html>
<html>
<body>
hello Rubick
<button id="showNotification">通知</button>
</body>
<script>
document.getElementById('showNotification').addEventListener('click', () => {
window.showNotification();
})
</script>
</html>
```
#### preload.js
细心的同学可能已经注意到上面的 `index.html` 使用了一个全局函数 `showNotification` 那么这个函数是在哪里定义的呢?
答案就是在 `preload.js` 里面。`preload.js` 可以为页面提供全局函数
```js
window.showNotification = function () {
rubick.showNotification('HI, rubick')
}
```
rubick 更多支持 API 能力参考:[rubick 全局API](https://github.com/rubickCenter/rubick/blob/master/public/preload.js)
### 测试写好的插件
由于 `rubick` 插件是基于 `npm` 的管理方式,所以开发者调试插件,也是基于 `npm` 的软连接的方式进行调试。
首先需要再插件 `package.json` 目录下执行:
```shell
$ npm link
```
然后将插件通过插件市场的 `开发者` 菜单进行安装,填写插件的 `name` 即可,如果插件需要调试,可以通过右上角 ... 来打开开发者工具进行调试,页面变更直接刷新即可:
![](https://pica.zhimg.com/80/v2-d7d6d5cba1151527aeff8e2c9b8cefb4_720w.gif)
本小节所有代码:[rubick-ui-plugin-demo](https://gitee.com/rubick-center/rubick-ui-plugin-demo)
## 开发系统插件
一个最基础插件的目录是这样的:
```
rubick-system-plugin-demo
|-- package.json
|-- index.js
```
### 文件说明
#### package.json
用于指定插件最基础的配置,一个最基础的配置信息如下:
```json
{
"name": "rubick-system-plugin-demo",
"pluginName": "rubick 系统插件demo",
"version": "0.0.0",
"description": "rubick 系统插件demo",
"entry": "index.js",
"logo": "https://xxxx/upload/202112/08/5bac90649c5343cabb63930b131cf8e6.png",
"pluginType": "system",
"author": "muwoo",
"homepage": ""
}
```
核心字段说明:
* name 插件 `npm` 包名称,<Badge type="tip" text="必填" />
* pluginName 插件显示名称,用于展示给使用者 <Badge type="tip" text="必填" />
* description 插件描述,描述这个插件的作用 <Badge type="tip" text="必填" />
* author 插件作者
* entry 入口文件,一般为 `index.js`
* logo 尺寸建议 200 * 200, 插件的 logo, 需要是 http/https 在线地址不支持本地logo <Badge type="tip" text="必填" />
* version 插件的版本 <Badge type="tip" text="必填" />
* homePage: 插件 readme raw 地址
* pluginType: 插件类型枚举ui, system. 当前选 system <Badge type="tip" text="必填" />
#### index.js
插件的入口文件,用于 rubick 主进程进行加载执行:
```js
module.exports = () => {
return {
onReady(ctx) {
const { Notification } = ctx;
new Notification({
title: "测试系统插件",
body: "这是一个系统插件在rubick运行时立即被加载"
}).show()
}
}
}
```
`index.js` 需要返回一个包含 `onReady` 生命周期的函数,该函数接受 `ctx` 对象作为参数,我们可以通过 `ctx` 使用 `electron` 主进程所有能力。
同时也为 `ctx` 上扩展挂在了 `mainWindow` 对象。
#### 调试插件
由于 `rubick` 插件是基于 `npm` 的管理方式,所以开发者调试插件,也是基于 `npm` 的软连接的方式进行调试。
首先需要再插件 `package.json` 目录下执行:
```shell
$ npm link
```
然后将插件通过插件市场的 `开发者` 菜单进行安装,填写插件的 `name` 即可。由于插件依赖于主进程启动执行,所以安装完成后需要重启 rubick 后才能生效。
![](https://pic3.zhimg.com/80/v2-e218500a0686a8735d80f417aa53b7aa_720w.gif)
::: danger
系统插件目前无法直接通过 `devtools` 进行调试,后面会进行优化
:::
## 发布插件
这里介绍完了如何开发插件,最后非常欢迎为 `rubick` 贡献开源插件,发布插件也非常简单,首先需要把自己的插件发布到 `npm` 仓库:
```shell
$ npm publish
```
然后再给 [rubick-database/plugins/total-plugins.json](https://gitcode.net/rubickcenter/rubick-database/-/blob/master/plugins/total-plugins.json) 仓库提个 `pull request`, 把你的 `package.json` 信息加入 `json` 文件内,等我们 merge 了您的提交,插件将会自动上架。

View File

@ -1,74 +0,0 @@
## 赞助
`rubick` 是非盈利项目,开源不容易,如果该项目对你有用的话,可以打赏我们喝杯 coffee ☕️.
<img width=200 src=https://pic1.zhimg.com/80/v2-688385687a37e962fe32daf136139feb_720w.png />
<img width=200 src=https://pica.zhimg.com/80/v2-1ba296fd2cece45ee1094ee7c259035c_720w.png />
## 前言
rubick 之前的插件管理,依托于云服务器存储,我们需要为服务器存储支付一笔不小的开销。
由于项目完全开源,所以几乎无任何收入,所以为了让 rubick 先生存下去,我们再三抉择把插件包管理方式托管到了`npm` 上。
由于 rubick 的插件管理体系是基于 npm 的包管理体系,所以当您需要使用插件的时候,需要手动保证当前电脑已经安装好了`node`环境。
如果当前电脑已经安装过 `node`,那么您可以直接下载 `rubick` 进行使用啦!
[macos 下安装 nodejs 方法](https://juejin.cn/post/6844903886541553672)
[windows 下安装 nodejs 方法](https://juejin.cn/post/6892790243687137287)
## 下载 rubick
[rubick 下载安装地址](https://github.com/rubickCenter/rubick/releases)
macos 选择 `pkg` 文件windows 选择 `exe` 文件Debian/Ubuntu选择`deb`
安装完成后打开 rubick 即可看到主搜索界面:
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/26f0fbe2c69246b6a3ed139b0df1ca0b~tplv-k3u1fbpfcp-watermark.image)
## 功能说明
接下来详细介绍 rubick 所包含和支持的功能
### 1. 搜索系统应用
支持拼音和缩写来搜索系统安装应用:
![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ba363e8f60f540e6a5c365c4317c4413~tplv-k3u1fbpfcp-watermark.image)
### 2. UI类插件安装
点击搜索框右侧 `rubick` 图标,进入插件市场,选择所需插件,点击下载按钮即可下载,下载完成后在已安装 tab 下可以找到安装插件。
安装完成后,输入插件呼起命令即可使用对应插件:
![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7ae45c7ede1f4e3bb7d35ae845e60b64~tplv-k3u1fbpfcp-watermark.image)
### 3. 系统类插件安装
系统插件安装方式和UI类一样在插件市场选择`系统分类`,寻找适合自己的系统插件安装即可。
::: danger
系统插件安装成功后,需要重启 `rubick` 才能生效
:::
### 4. 输入框聚焦自动根据剪切板内容匹配插件
`rubick` 内搜索`偏好设置`,然后开启`自动粘贴` 功能,即可匹配剪切板内容自动匹配适合插件进行使用。
![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/01ef50fbfa064ba9a88bebe1531eacd4~tplv-k3u1fbpfcp-watermark.image)
### 内网部署
::: tip
如果把插件发布到公网 `npm` 如果不符合您的公司安全要求,`rubick` 支持内网私有源和私有插件库,如果您需要内网部署使用,可以自行配置以下规则。
:::
`rubick` 依赖 `npm` 仓库做插件管理,依赖 `gitcode` 做插件数据存储所以如果要进行内网部署主要需要替换这2个设置。详细设置
`插件市场 -> 设置 -> 内网部署设置`
![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1319b177fb544017ae10b4a703e8efa6~tplv-k3u1fbpfcp-watermark.image?)
#### 1. 替换 npm 源
插件发布到私有 `npm` 源即可。
#### 2. 替换 `gitcode` 源为内网 `gitlab`: database url
* 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`
### 更多功能
如果您还需要更多功能,欢迎来这里给我们提建议:[issues](https://github.com/rubickCenter/rubick/issues) 。
有价值的想法我们会加入到后期的开发当中。同时也欢迎一起加入共建。

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

View File

@ -1,103 +0,0 @@
## 赞助
`rubick` 是非盈利项目,开源不容易,如果该项目对你有用的话,可以打赏我们喝杯 coffee ☕️.
<img width=200 src=https://pic1.zhimg.com/80/v2-688385687a37e962fe32daf136139feb_720w.png />
<img width=200 src=https://pica.zhimg.com/80/v2-1ba296fd2cece45ee1094ee7c259035c_720w.png />
## 贡献代码
### rubick 目录介绍
```shell
.
├── docs # 文档存方目录
│   ├── docs
│   ├── package-lock.json
│   ├── package.json
│   └── pnpm-lock.yaml
├── feature # 插件市场插件
│   ├── README.md
│   ├── babel.config.js
│   ├── package-lock.json
│   ├── package.json
│   ├── public
│   ├── src
│   ├── tsconfig.json
│   └── vue.config.js
├── public # rubick __static 目录
│   ├── favicon.ico
│   ├── feature
│   ├── icons
│   ├── index.html
│   ├── preload.js
│   └── tpl
├── src # rubick 核心源码
│   ├── common # 一些通用的函数
│   ├── core # 一些核心的能力,比如 app search
│   ├── main # 主进程
│   └── renderer # 渲染进程
├── tpl # rubick 模板插件
│   ├── README.md
│   ├── babel.config.js
│   ├── package-lock.json
│   ├── package.json
│   ├── public
│   ├── src
│   ├── tsconfig.json
│   └── vue.config.js
├── LICENSE # MIT 协议
├── README.md # 英文文档
├── README.zh-CN.md # 中文文档
├── babel.config.js
├── deploy-doc.sh # rubick doc 发布脚本
├── tsconfig.json
├── package-lock.json
├── package.json
└── vue.config.js
```
### 启动
#### 1. 安装依赖
`rubick` 启动主要涉及到3个目录
1. 根目录:`rubick` 核心进程
2. feature`rubick` 内置的插件市场插件
3. tpl: `rubick` 内置的模板插件
```shell
$ npm i
$ cd feature && npm i
$ cd tpl && npm i
```
#### 2. 启动核心进程
```shell
$ npm run electron:serve
```
#### 3. 启动插件中心 <Badge type="warning" text="非必须" vertical="top" />
```shell
$ cd feature && npm run serve
```
#### 4. 启动模板插件 <Badge type="warning" text="非必须" vertical="top" />
```shell
$ cd tpl && npm run serve
```
### 编译
```shell
$ cd feature && npm run build
$ cd tpl && npm run build
$ npm run electron:build
```
### PR
1. Create an issue about the features, such as new components.
2. Fork the repo to your own account.
3. Clone your fork.
4. Create a new branch base on dev, if you want to add new component, the branch name should be formatted as component-[Component Name]. (e.g. component-steps) And the commit info should be formatted as [Component Name]: Info about commit.
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.

View File

@ -1,19 +0,0 @@
# 特殊服务
## 说明
`rubick` 一直坚持开源免费,现在不会变,以后也不会变。但是纯开源 `MIT` 模式下,是一种 0 收入用爱发电的,完全依靠
作者自己的爱好和激情。但这种用爱发电的模式很难持续维持,为了更好的持续迭代和发展壮大 `rubick`, 我们需要一定的现金持续激励 `rubick` 的核心开发者们,让更多的人成为 `rubick`
的核心开发者。所以 `rubick` 开启了一个新的模式尝试,那是服务付费:`rubick` 用户可以购买我们提供技术支持、答疑解惑、定制化插件开发、二次定制化开发 `rubick` 等等官方服务...
## 可以提供哪些服务?
我们收集了大量用户的问题,目前约定可以支持到的服务有:
1. 二次定制化开发 `rubick`
2. 轻量级插件开发
3. `rubick` 实现原理手把手介绍
4. `rubick` 使用答疑
5. `rubick` 内网部署一条龙服务
6. 前端圈各种技术支持(作者分别是前蚂蚁集团和字节跳动的前端技术专家)
7. 未来能提供的一切...
## 如何加入特殊服务?
扫描下方的二维码,加入知识星球即可:
<img width=400 src=https://picx.zhimg.com/80/v2-6deabf65175d18080439ef813102d18c_720w.png />

View File

@ -1,15 +0,0 @@
{
"name": "rubick-docs",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"docs:dev": "vuepress dev docs",
"docs:build": "vuepress build docs"
},
"author": "muwoo",
"license": "ISC",
"devDependencies": {
"vuepress": "^1.8.2"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
"pluginName": "系统菜单",
"description": "系统菜单",
"main": "index.html",
"logo": "https://pic1.zhimg.com/80/v2-c09780808301668a82e6646cb42f0806_720w.png",
"logo": "https://pic1.zhimg.com/80/v2-29152fe716010751db835adf591421f8_720w.png",
"version": "0.0.0",
"preload":"preload.js",
"pluginType": "ui",
@ -18,7 +18,7 @@
"code": "installed",
"explain": "已安装插件",
"cmds":[
"已安装插件"
"已安装插件", "installed"
]
},{
"code": "settings",

View File

@ -8,37 +8,37 @@
>
<a-menu-item key="finder">
<template #icon>
<StarOutlined style="font-size: 18px;" />
<StarOutlined style="font-size: 16px" />
</template>
{{ $t('feature.market.explore') }}
</a-menu-item>
<a-menu-item key="worker">
<template #icon>
<SendOutlined style="transform: rotate(-45deg); font-size: 18px;" />
<SendOutlined style="transform: rotate(-45deg); font-size: 16px" />
</template>
{{ $t('feature.market.efficiency') }}
</a-menu-item>
<a-menu-item key="tools">
<template #icon>
<SearchOutlined style="font-size: 18px;" />
<SearchOutlined style="font-size: 16px" />
</template>
{{ $t('feature.market.searchTool') }}
</a-menu-item>
<a-menu-item key="image">
<template #icon>
<FileImageOutlined style="font-size: 18px;" />
<FileImageOutlined style="font-size: 16px" />
</template>
{{ $t('feature.market.imageTool') }}
</a-menu-item>
<a-menu-item key="devPlugin">
<template #icon>
<CodeOutlined style="font-size: 18px;" />
<CodeOutlined style="font-size: 16px" />
</template>
{{ $t('feature.market.developTool') }}
</a-menu-item>
<a-menu-item key="system">
<template #icon>
<DatabaseOutlined style="font-size: 18px;" />
<DatabaseOutlined style="font-size: 16px" />
</template>
{{ $t('feature.market.systemTool') }}
</a-menu-item>
@ -72,7 +72,21 @@
</a-sub-menu>
</a-menu>
</div>
<div :class="['finder', 'result', 'devPlugin', 'image', 'tools', 'worker', 'system'].includes(active[0]) ? 'container' : 'more'">
<div
:class="
[
'finder',
'result',
'devPlugin',
'image',
'tools',
'worker',
'system',
].includes(active[0])
? 'container'
: 'more'
"
>
<keep-alive>
<router-view />
</keep-alive>
@ -103,13 +117,14 @@ const active = computed(() => store.state.active);
const { perf } = localConfig.getConfig();
const changeMenu = (key: any) => {
store.commit('commonUpdate', {active: [key]})
store.commit('commonUpdate', { active: [key] });
router.push(key);
};
window.rubick.onPluginEnter(({ code }: { code: string }) => {
code = code === '已安装插件' ? 'installed' : code;
changeMenu(code);
store.commit('commonUpdate', {active: [code]})
store.commit('commonUpdate', { active: [code] });
});
window.rubick.setSubInput((e: any) => {
@ -128,7 +143,7 @@ window.rubick.setSubInput((e: any) => {
store.commit('setSearchValue', e.text);
router.push('result');
} else {
store.commit('commonUpdate', {active: ['finder']})
store.commit('commonUpdate', { active: ['finder'] });
router.push('finder');
}
}
@ -143,13 +158,16 @@ init();
background: var(--color-body-bg2) !important;
height: 100%;
border-right: none;
.ant-menu-item, .ant-menu-submenu, .ant-menu-submenu-arrow {
.ant-menu-item,
.ant-menu-submenu,
.ant-menu-submenu-arrow {
color: var(--color-text-content);
&:active {
background: none;
}
}
.ant-menu-item-selected, .ant-menu-submenu-selected {
.ant-menu-item-selected,
.ant-menu-submenu-selected {
background-color: var(--color-list-hover);
color: var(--ant-primary-color);
.ant-menu-submenu-arrow {
@ -202,9 +220,12 @@ init();
background: var(--color-body-bg2);
}
.left-menu {
padding: 24px 16px;
padding: 16px;
position: relative;
height: 100vh;
:deep(.ant-menu) {
width: 100%;
}
:deep(.ant-menu-item) {
padding-left: 12px !important;
display: flex;
@ -218,7 +239,14 @@ init();
}
:deep(.user-info) {
position: absolute;
bottom: 32px;
bottom: 16px;
width: calc(100% - 32px);
.ant-menu-submenu-title {
padding: 0 32px 0 8px;
.ant-menu-title-content {
margin-left: 8px;
}
}
}
:deep(.ant-avatar) {
background: transparent;

View File

@ -1,8 +1,3 @@
@import "~ant-design-vue/dist/antd.less"; // 引入官方提供的 less 样式入口文件
@primary-color: #ff4ea4; // 全局主色
@error-color: #ff4ea4; // 错误色
:root {
--color-text-primary: rgba(0, 0, 0, 0.85);
--color-text-content: #141414;

Binary file not shown.

After

Width:  |  Height:  |  Size: 845 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,6 +1,6 @@
import axios from 'axios';
let baseURL = 'https://gitcode.net/rubickcenter/rubick-database/-/raw/master';
let baseURL = 'https://gitee.com/monkeyWang/rubickdatabase/raw/master';
let access_token = '';
try {
@ -14,7 +14,7 @@ try {
const instance = axios.create({
timeout: 4000,
baseURL:
baseURL || 'https://gitcode.net/rubickcenter/rubick-database/-/raw/master',
baseURL || 'https://gitee.com/monkeyWang/rubickdatabase/raw/master',
});
export default {
@ -23,9 +23,10 @@ export default {
if (access_token) {
targetPath = `${encodeURIComponent(
targetPath
)}/raw?access_token=${access_token}&ref=master`;
)}?access_token=${access_token}&ref=master`;
}
const res = await instance.get(targetPath);
console.log('total plugsin', res);
return res.data;
},
@ -34,7 +35,7 @@ export default {
if (access_token) {
targetPath = `${encodeURIComponent(
targetPath
)}/raw?access_token=${access_token}&ref=master`;
)}?access_token=${access_token}&ref=master`;
}
const res = await instance.get(targetPath);
return res.data;
@ -45,7 +46,7 @@ export default {
if (access_token) {
targetPath = `${encodeURIComponent(
targetPath
)}/raw?access_token=${access_token}&ref=master`;
)}?access_token=${access_token}&ref=master`;
}
const res = await instance.get(targetPath);
return res.data;
@ -55,7 +56,7 @@ export default {
if (access_token) {
targetPath = `${encodeURIComponent(
targetPath
)}/raw?access_token=${access_token}&ref=master`;
)}?access_token=${access_token}&ref=master`;
}
const res = await instance.get(targetPath);
return res.data;
@ -71,7 +72,7 @@ export default {
if (access_token) {
targetPath = `${encodeURIComponent(
targetPath
)}/raw?access_token=${access_token}&ref=master`;
)}?access_token=${access_token}&ref=master`;
}
const res = await instance.get(targetPath);
return res.data;
@ -81,7 +82,7 @@ export default {
if (access_token) {
targetPath = `${encodeURIComponent(
targetPath
)}/raw?access_token=${access_token}&ref=master`;
)}?access_token=${access_token}&ref=master`;
}
const res = await instance.get(targetPath);
return res.data;
@ -91,7 +92,7 @@ export default {
if (access_token) {
targetPath = `${encodeURIComponent(
targetPath
)}/raw?access_token=${access_token}&ref=master`;
)}?access_token=${access_token}&ref=master`;
}
const res = await instance.get(targetPath);
return res.data;

View File

@ -67,6 +67,7 @@ export default {
changeLang: 'Change Language',
cn: '简体中文',
en: 'English',
history: 'keywords search history',
},
global: {
title: 'Global Shortcut Key',

View File

@ -65,6 +65,7 @@ export default {
changeLang: '切换语言',
cn: '简体中文',
en: 'English',
history: '关键词搜索记录',
},
global: {
title: '全局快捷键',

View File

@ -33,6 +33,12 @@ import localConfig from './confOp';
const config: any = localConfig.getConfig();
// 暗夜模式
if (config.perf.common.darkMode) {
document.body.classList.add('dark');
window.rubick.theme = 'dark';
}
ConfigProvider.config({
theme: config.perf.custom || {},
});

View File

@ -185,7 +185,8 @@ const addCmdToSuperPanel = ({ cmd, code }) => {
},
};
superPanelPlugins.value.data.push(plugin);
window.rubick.db.put(toRaw(superPanelPlugins.value));
const { rev } = window.rubick.db.put(JSON.parse(JSON.stringify(superPanelPlugins.value)));
superPanelPlugins.value._rev = rev;
};
const removePluginToSuperPanel = ({ cmd, name }) => {
@ -195,7 +196,8 @@ const removePluginToSuperPanel = ({ cmd, name }) => {
return item.cmd !== cmd;
}
);
window.rubick.db.put(toRaw(superPanelPlugins.value));
const { rev } = window.rubick.db.put(toRaw(superPanelPlugins.value));
superPanelPlugins.value._rev = rev;
};
const hasAdded = (cmd) => {

View File

@ -7,7 +7,7 @@
:data-source="list.filter((item) => !!item)"
>
<template #renderItem="{ item, index }">
<a-list-item v-if="item" @click="showDetail(item)">
<a-list-item v-if="item" @click="showDetail(index)">
<template #actions>
<a-button
class="download-plugin-btn"
@ -105,7 +105,7 @@ import {
SelectOutlined
} from '@ant-design/icons-vue';
import { defineProps, ref } from 'vue';
import { defineProps, ref, computed } from 'vue';
import { useStore } from 'vuex';
import { message } from 'ant-design-vue';
import MarkdownIt from 'markdown-it';
@ -121,7 +121,7 @@ const router = useRouter();
const startDownload = (name) => store.dispatch('startDownload', name);
const successDownload = (name) => store.dispatch('successDownload', name);
defineProps({
const props = defineProps({
list: {
type: [Array],
default: () => [],
@ -137,13 +137,14 @@ const downloadPlugin = async (plugin) => {
};
const visible = ref(false);
const detail = ref({});
const showIndex = ref(0);
const markdown = new MarkdownIt();
const content = ref('');
const showDetail = async (item) => {
const showDetail = async (index) => {
const item = props.list[index];
visible.value = true;
detail.value = item;
showIndex.value = index;
content.value = '';
let mdContent = '暂无内容';
try {
@ -156,6 +157,8 @@ const showDetail = async (item) => {
}
};
const detail = computed(() => props.list[showIndex.value]);
const openPlugin = (item) => {
store.commit('commonUpdate', {active: ['installed']})
router.push({

View File

@ -31,9 +31,9 @@ const searchValue = computed(() => store.state.searchValue);
const result = computed(() => {
if (searchValue.value.trim().length > 0) {
const pattern = new RegExp(searchValue.value);
const pattern = new RegExp(searchValue.value.toLowerCase());
return totalPlugins.value.filter((plugin) => {
if (plugin.pluginName.match(pattern)) {
if (plugin.pluginName.toLowerCase().match(pattern)) {
return true;
} else {
return false;

View File

@ -119,6 +119,16 @@
:un-checked-children="$t('feature.settings.basic.off')"
></a-switch>
</div>
<div class="settings-item-li">
<div class="label">
{{ $t('feature.settings.basic.history') }}
</div>
<a-switch
v-model:checked="common.history"
:checked-children="$t('feature.settings.basic.on')"
:un-checked-children="$t('feature.settings.basic.off')"
></a-switch>
</div>
</div>
<div class="setting-item">
<div class="title">{{ $t('feature.settings.basic.theme') }}</div>
@ -264,12 +274,16 @@ const state = reactive({
custom: {},
});
// lastKeyPressTime
const lastKeyPressTime = ref(0);
const DOUBLE_CLICK_THRESHOLD = 300; //
const isWindows = window?.rubick?.isWindows();
const tipText = computed(() => {
const optionKeyName = isWindows ? 'Alt' : 'Option、Command';
return t('feature.settings.global.addShortcutKeyTips', {
optionKeyName: optionKeyName,
});
}) + `此外你也可以双击修饰键如Ctrl+Ctrl`;
});
const currentSelect = ref(['userInfo']);
@ -283,14 +297,15 @@ state.local = perf.local;
state.global = defaultGlobal;
const setConfig = debounce(() => {
const { perf } = localConfig.getConfig();
localConfig.setConfig(
JSON.parse(
JSON.stringify({
perf: {
...perf,
shortCut: state.shortCut,
common: state.common,
local: state.local,
custom: state.custom,
},
global: state.global,
})
@ -303,33 +318,60 @@ watch(state, setConfig);
const changeShortCut = (e, key) => {
let compose = '';
//
let incluFuncKeys = false;
const currentTime = Date.now();
const isDoubleClick = currentTime - lastKeyPressTime.value < DOUBLE_CLICK_THRESHOLD;
lastKeyPressTime.value = currentTime;
// F1-F12
if (e.keyCode >= 112 && e.keyCode <= 123) {
state.shortCut[key] = keycodes[e.keyCode].toUpperCase();
return;
}
//
if (isDoubleClick) {
if (e.keyCode === 17) { // Ctrl
state.shortCut[key] = 'Ctrl+Ctrl';
return;
}
if (e.keyCode === 18) { // Alt
state.shortCut[key] = 'Option+Option';
return;
}
if (e.keyCode === 16) { // Shift
state.shortCut[key] = 'Shift+Shift';
return;
}
if (e.keyCode === 93) { // Command
state.shortCut[key] = 'Command+Command';
return;
}
}
// +
let hasModifierKey = false;
if (e.ctrlKey && e.keyCode !== 17) {
compose += '+Ctrl';
incluFuncKeys = true;
hasModifierKey = true;
}
if (e.shiftKey && e.keyCode !== 16) {
compose += '+Shift';
incluFuncKeys = true;
hasModifierKey = true;
}
if (e.altKey && e.keyCode !== 18) {
compose += '+Option';
incluFuncKeys = true;
hasModifierKey = true;
}
if (e.metaKey && e.keyCode !== 93) {
compose += '+Command';
incluFuncKeys = true;
hasModifierKey = true;
}
compose += '+' + keycodes[e.keyCode].toUpperCase();
compose = compose.substring(1);
if (
incluFuncKeys &&
e.keyCode !== 16 &&
e.keyCode !== 17 &&
e.keyCode !== 18 &&
e.keyCode !== 93
) {
//
if (hasModifierKey) {
compose += '+' + keycodes[e.keyCode].toUpperCase();
compose = compose.substring(1);
state.shortCut[key] = compose;
} else {
//

View File

@ -17,7 +17,7 @@
name="register"
>
<a-input
placeholder="https://registry.npm.taobao.org"
placeholder="https://registry.npmmirror.com"
v-model:value="formState.register"
/>
</a-form-item>
@ -27,7 +27,7 @@
name="database"
>
<a-input
placeholder="https://gitcode.net/rubickcenter/rubick-database/-/raw/master"
placeholder="https://gitee.com/monkeyWang/rubickdatabase/raw/master"
v-model:value="formState.database"
/>
</a-form-item>
@ -54,8 +54,8 @@ import { message } from 'ant-design-vue';
let _rev: any;
let defaultConfig = {
register: 'https://registry.npm.taobao.org',
database: 'https://gitcode.net/rubickcenter/rubick-database/-/raw/master',
register: 'https://registry.npmmirror.com',
database: 'https://gitee.com/monkeyWang/rubickdatabase/raw/master',
access_token: '',
};
@ -81,7 +81,7 @@ const layout = {
const resetForm = () => {
formState.value = {
register: 'https://registry.npmmirror.com',
database: 'https://gitcode.net/rubickcenter/rubick-database/-/raw/master',
database: 'https://gitee.com/monkeyWang/rubickdatabase/raw/master',
access_token: '',
};
};

View File

@ -64,6 +64,8 @@ const theme = ref(perf.custom.theme);
state.custom = perf.custom || {};
const setConfig = debounce(() => {
const { perf } = localConfig.getConfig();
localConfig.setConfig(
JSON.parse(
JSON.stringify({

View File

@ -1,6 +1,6 @@
{
"name": "rubick",
"version": "4.1.0-beta.2",
"version": "4.3.5",
"author": "muwoo <2424880409@qq.com>",
"private": true,
"scripts": {
@ -30,7 +30,7 @@
"fix-path": "^3.0.0",
"get-mac-apps": "^1.0.2",
"got": "^11.8.3",
"lodash.throttle": "^4.1.1",
"lodash.debounce": "^4.0.8",
"memorystream": "^0.3.1",
"node-key-sender": "^1.0.11",
"npm": "6.14.7",
@ -39,6 +39,7 @@
"pouchdb-load": "^1.4.6",
"pouchdb-replication-stream": "^1.2.9",
"simple-plist": "0.2.1",
"uiohook-napi": "^1.5.4",
"vue": "^3.0.0",
"vue-router": "^4.0.0-0",
"vuex": "^4.0.0-0",
@ -46,6 +47,7 @@
"worker-loader": "^3.0.8"
},
"devDependencies": {
"@electron/asar": "^3.2.8",
"@ts-type/package-dts": "^1.0.53",
"@types/electron-devtools-installer": "^2.2.0",
"@typescript-eslint/eslint-plugin": "^4.18.0",
@ -60,6 +62,7 @@
"@vue/eslint-config-prettier": "^6.0.0",
"@vue/eslint-config-typescript": "^7.0.0",
"babel-plugin-import": "^1.13.3",
"compressing": "^1.10.0",
"electron": "26.0.0",
"electron-builder": "22.13.1",
"electron-devtools-installer": "^3.1.0",

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.ant-menu-submenu-popup .ant-menu{background:var(--color-body-bg2)!important;height:100%;border-right:none}.ant-menu-submenu-popup .ant-menu .ant-menu-item,.ant-menu-submenu-popup .ant-menu .ant-menu-submenu,.ant-menu-submenu-popup .ant-menu .ant-menu-submenu-arrow{color:var(--color-text-content)}.ant-menu-submenu-popup .ant-menu .ant-menu-item:active,.ant-menu-submenu-popup .ant-menu .ant-menu-submenu-arrow:active,.ant-menu-submenu-popup .ant-menu .ant-menu-submenu:active{background:none}.ant-menu-submenu-popup .ant-menu .ant-menu-item-selected,.ant-menu-submenu-popup .ant-menu .ant-menu-submenu-selected{background-color:var(--color-list-hover);color:var(--ant-primary-color)}.ant-menu-submenu-popup .ant-menu .ant-menu-item-selected .ant-menu-submenu-arrow,.ant-menu-submenu-popup .ant-menu .ant-menu-submenu-selected .ant-menu-submenu-arrow{color:var(--ant-primary-color)}.ant-menu-submenu-popup .ant-menu .ant-menu-item-selected:after,.ant-menu-submenu-popup .ant-menu .ant-menu-submenu-selected:after{display:none}.left-menu[data-v-435a1273]{width:183px;border-right:1px solid var(--color-border-light)}.left-menu .search-container[data-v-435a1273]{padding:10px}.left-menu .ant-input-affix-wrapper[data-v-435a1273]{border:none;background:var(--color-input-hover)}.left-menu .ant-input-affix-wrapper[data-v-435a1273] input{background:none;color:var(--color-text-desc)}.left-menu .ant-input-affix-wrapper[data-v-435a1273] .anticon{color:var(--color-text-desc)}.left-menu[data-v-435a1273] .ant-menu{background:var(--color-menu-bg);height:100%;border-right:none}.left-menu[data-v-435a1273] .ant-menu .ant-menu-item,.left-menu[data-v-435a1273] .ant-menu .ant-menu-submenu,.left-menu[data-v-435a1273] .ant-menu .ant-menu-submenu-arrow{color:var(--color-text-content)}.left-menu[data-v-435a1273] .ant-menu .ant-menu-item:active,.left-menu[data-v-435a1273] .ant-menu .ant-menu-submenu-arrow:active,.left-menu[data-v-435a1273] .ant-menu .ant-menu-submenu:active{background:none}.left-menu[data-v-435a1273] .ant-menu .ant-menu-item-selected,.left-menu[data-v-435a1273] .ant-menu .ant-menu-submenu-selected{background-color:var(--color-list-hover);color:var(--ant-primary-color)}.left-menu[data-v-435a1273] .ant-menu .ant-menu-item-selected .ant-menu-submenu-arrow,.left-menu[data-v-435a1273] .ant-menu .ant-menu-submenu-selected .ant-menu-submenu-arrow{color:var(--ant-primary-color)}.left-menu[data-v-435a1273] .ant-menu .ant-menu-item-selected:after,.left-menu[data-v-435a1273] .ant-menu .ant-menu-submenu-selected:after{display:none}[data-v-435a1273]{margin:0;padding:0}.main-container[data-v-435a1273]{-webkit-app-region:no-drag;display:flex;background:var(--color-body-bg);border-top:1px solid var(--color-border-light);height:100vh;box-sizing:border-box;align-items:flex-start;width:100%;overflow:hidden;background:var(--color-menu-bg)}.main-container .search[data-v-435a1273] .ant-btn,.main-container .search[data-v-435a1273] .ant-input,.main-container .search[data-v-435a1273] .ant-input-group-addon{color:var(--ant-primary-color)!important;background:var(--color-input-hover);border-color:var(--color-border-light)}.main-container .container[data-v-435a1273],.main-container .more[data-v-435a1273]{background:var(--color-body-bg);width:calc(100% - 183px);height:100%;box-sizing:border-box;padding:16px;position:relative;overflow:auto}.main-container .more[data-v-435a1273]{background:var(--color-body-bg2)}.main-container .left-menu[data-v-435a1273]{padding:24px 16px;position:relative;height:100vh}.main-container .left-menu[data-v-435a1273] .ant-menu-item{padding-left:12px!important;display:flex;align-items:center}.main-container .left-menu[data-v-435a1273] .ant-menu-item-selected,.main-container .left-menu[data-v-435a1273] .ant-menu-submenu-selected{background-color:var(--color-list-hover);border-radius:6px;color:var(--ant-primary-color)}.main-container .left-menu[data-v-435a1273] .user-info{position:absolute;bottom:32px}.main-container .left-menu[data-v-435a1273] .ant-avatar{background:transparent}:root{--color-text-primary:rgba(0,0,0,0.85);--color-text-content:#141414;--color-text-desc:rgba(0,0,0,0.45);--color-body-bg2:#eee;--color-body-bg:#fff;--color-menu-bg:#f8f8f8;--color-list-hover:#e9e9e9;--color-input-hover:#fff;--color-border-light:#f0f0f0;--color-action-color:rgba(0,0,0,0.25)}.dark{--color-text-primary:#e8e8f0;--color-text-content:#ccccd8;--color-text-desc:#8f8fa6;--color-body-bg:#1c1c28;--color-body-bg2:#2c2f3b;--color-menu-bg:#1c1c28;--color-list-hover:#2c2f3b;--color-input-hover:rgba(68,68,68,0.8666666666666667);--color-border-light:rgba(68,68,68,0.8666666666666667);--color-action-color:hsla(0,0%,100%,0.30196078431372547)}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
.ant-message{box-sizing:border-box;margin:0;padding:0;color:rgba(0,0,0,.85);font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:fixed;top:8px;left:0;z-index:1010;width:100%;pointer-events:none}.ant-message-notice{padding:8px;text-align:center}.ant-message-notice-content{display:inline-block;padding:10px 16px;background:#fff;border-radius:2px;box-shadow:0 3px 6px -4px rgba(0,0,0,.12),0 6px 16px 0 rgba(0,0,0,.08),0 9px 28px 8px rgba(0,0,0,.05);pointer-events:all}.ant-message-success .anticon{color:#52c41a}.ant-message-error .anticon{color:#ff4d4f}.ant-message-warning .anticon{color:#faad14}.ant-message-info .anticon,.ant-message-loading .anticon{color:#1890ff}.ant-message .anticon{position:relative;top:1px;margin-right:8px;font-size:16px}.ant-message-notice.ant-move-up-leave.ant-move-up-leave-active{-webkit-animation-name:MessageMoveOut;animation-name:MessageMoveOut;-webkit-animation-duration:.3s;animation-duration:.3s}@-webkit-keyframes MessageMoveOut{0%{max-height:150px;padding:8px;opacity:1}to{max-height:0;padding:0;opacity:0}}@keyframes MessageMoveOut{0%{max-height:150px;padding:8px;opacity:1}to{max-height:0;padding:0;opacity:0}}.ant-message-rtl,.ant-message-rtl span{direction:rtl}.ant-message-rtl .anticon{margin-right:0;margin-left:8px}.dev[data-v-6fb0031c]{box-sizing:border-box;width:100%;overflow-x:hidden;height:calc(100vh - 34px)}.dev .view-title[data-v-6fb0031c]{font-size:16px;font-weight:500;margin-bottom:16px;color:var(--color-text-primary)}.dev .view-container[data-v-6fb0031c]{padding:10px;box-sizing:border-box;border-radius:8px;background:var(--color-body-bg);overflow:auto;height:calc(100vh - 84px)}.dev[data-v-6fb0031c] label{color:var(--color-text-content)}.dev[data-v-6fb0031c] .ant-input{background:var(--color-input-hover);color:var(--color-text-content)}
.ant-message{box-sizing:border-box;margin:0;padding:0;color:rgba(0,0,0,.85);font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:fixed;top:8px;left:0;z-index:1010;width:100%;pointer-events:none}.ant-message-notice{padding:8px;text-align:center}.ant-message-notice-content{display:inline-block;padding:10px 16px;background:#fff;border-radius:2px;box-shadow:0 3px 6px -4px rgba(0,0,0,.12),0 6px 16px 0 rgba(0,0,0,.08),0 9px 28px 8px rgba(0,0,0,.05);pointer-events:all}.ant-message-success .anticon{color:#52c41a}.ant-message-error .anticon{color:#ff4d4f}.ant-message-warning .anticon{color:#faad14}.ant-message-info .anticon,.ant-message-loading .anticon{color:#1890ff}.ant-message .anticon{position:relative;top:1px;margin-right:8px;font-size:16px}.ant-message-notice.ant-move-up-leave.ant-move-up-leave-active{-webkit-animation-name:MessageMoveOut;animation-name:MessageMoveOut;-webkit-animation-duration:.3s;animation-duration:.3s}@-webkit-keyframes MessageMoveOut{0%{max-height:150px;padding:8px;opacity:1}to{max-height:0;padding:0;opacity:0}}@keyframes MessageMoveOut{0%{max-height:150px;padding:8px;opacity:1}to{max-height:0;padding:0;opacity:0}}.ant-message-rtl,.ant-message-rtl span{direction:rtl}.ant-message-rtl .anticon{margin-right:0;margin-left:8px}.dev[data-v-2d26bea2]{box-sizing:border-box;width:100%;overflow-x:hidden;height:calc(100vh - 34px)}.dev .view-title[data-v-2d26bea2]{font-size:16px;font-weight:500;margin-bottom:16px;color:var(--color-text-primary)}.dev .view-container[data-v-2d26bea2]{padding:10px;box-sizing:border-box;border-radius:8px;background:var(--color-body-bg);overflow:auto;height:calc(100vh - 84px)}.dev[data-v-2d26bea2] label{color:var(--color-text-content)}.dev[data-v-2d26bea2] .ant-input{background:var(--color-input-hover)!important;color:var(--color-text-content)}

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>feature</title><link href="css/chunk-0add5e88.2f22e37d.css" rel="prefetch"><link href="css/chunk-111de227.2450c00b.css" rel="prefetch"><link href="css/chunk-1af68a6e.2450c00b.css" rel="prefetch"><link href="css/chunk-1e4a75e5.ba6f3d8b.css" rel="prefetch"><link href="css/chunk-3fb623ce.2b9b7de2.css" rel="prefetch"><link href="css/chunk-596c6184.9be2495c.css" rel="prefetch"><link href="css/chunk-5cf3b9db.e273616c.css" rel="prefetch"><link href="css/chunk-88e69aa8.69c3b24d.css" rel="prefetch"><link href="css/chunk-93f94cf8.0f63dd4a.css" rel="prefetch"><link href="css/chunk-a2b32e48.67429700.css" rel="prefetch"><link href="css/chunk-cf61e458.9be2495c.css" rel="prefetch"><link href="css/chunk-f69c766e.9be2495c.css" rel="prefetch"><link href="js/chunk-0add5e88.26781f59.js" rel="prefetch"><link href="js/chunk-111de227.86b2c5e3.js" rel="prefetch"><link href="js/chunk-1af68a6e.2022b1a8.js" rel="prefetch"><link href="js/chunk-1e4a75e5.e9c5b1d4.js" rel="prefetch"><link href="js/chunk-2d0c49e7.20196ed0.js" rel="prefetch"><link href="js/chunk-3fb623ce.ee432c33.js" rel="prefetch"><link href="js/chunk-596c6184.a1398c77.js" rel="prefetch"><link href="js/chunk-5cf3b9db.d5ee71ed.js" rel="prefetch"><link href="js/chunk-88e69aa8.55955c4d.js" rel="prefetch"><link href="js/chunk-93f94cf8.7dd5e910.js" rel="prefetch"><link href="js/chunk-a2b32e48.20d42be1.js" rel="prefetch"><link href="js/chunk-cf61e458.20835e3d.js" rel="prefetch"><link href="js/chunk-f69c766e.230d2fbd.js" rel="prefetch"><link href="css/app.4abdfe3a.css" rel="preload" as="style"><link href="css/chunk-vendors.a52bdfa2.css" rel="preload" as="style"><link href="js/app.313735e9.js" rel="preload" as="script"><link href="js/chunk-vendors.c7dcd677.js" rel="preload" as="script"><link href="css/chunk-vendors.a52bdfa2.css" rel="stylesheet"><link href="css/app.4abdfe3a.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but feature doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.c7dcd677.js"></script><script src="js/app.313735e9.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>feature</title><link href="css/chunk-0add5e88.2f22e37d.css" rel="prefetch"><link href="css/chunk-111de227.2450c00b.css" rel="prefetch"><link href="css/chunk-197bc330.29812a6a.css" rel="prefetch"><link href="css/chunk-1af68a6e.2450c00b.css" rel="prefetch"><link href="css/chunk-3fb623ce.2b9b7de2.css" rel="prefetch"><link href="css/chunk-46496dac.da060b5a.css" rel="prefetch"><link href="css/chunk-596c6184.9be2495c.css" rel="prefetch"><link href="css/chunk-88e69aa8.69c3b24d.css" rel="prefetch"><link href="css/chunk-93f94cf8.0f63dd4a.css" rel="prefetch"><link href="css/chunk-a2b32e48.67429700.css" rel="prefetch"><link href="css/chunk-cf61e458.9be2495c.css" rel="prefetch"><link href="css/chunk-f69c766e.9be2495c.css" rel="prefetch"><link href="js/chunk-0add5e88.26781f59.js" rel="prefetch"><link href="js/chunk-111de227.86b2c5e3.js" rel="prefetch"><link href="js/chunk-197bc330.95c96fee.js" rel="prefetch"><link href="js/chunk-1af68a6e.2022b1a8.js" rel="prefetch"><link href="js/chunk-2d0c49e7.20196ed0.js" rel="prefetch"><link href="js/chunk-3fb623ce.ee432c33.js" rel="prefetch"><link href="js/chunk-46496dac.719cab20.js" rel="prefetch"><link href="js/chunk-596c6184.a1398c77.js" rel="prefetch"><link href="js/chunk-88e69aa8.55955c4d.js" rel="prefetch"><link href="js/chunk-93f94cf8.7dd5e910.js" rel="prefetch"><link href="js/chunk-a2b32e48.20d42be1.js" rel="prefetch"><link href="js/chunk-cf61e458.20835e3d.js" rel="prefetch"><link href="js/chunk-f69c766e.230d2fbd.js" rel="prefetch"><link href="css/app.bb291762.css" rel="preload" as="style"><link href="css/chunk-vendors.a52bdfa2.css" rel="preload" as="style"><link href="js/app.55a0112a.js" rel="preload" as="script"><link href="js/chunk-vendors.c7dcd677.js" rel="preload" as="script"><link href="css/chunk-vendors.a52bdfa2.css" rel="stylesheet"><link href="css/app.bb291762.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but feature doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.c7dcd677.js"></script><script src="js/app.55a0112a.js"></script></body></html>

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 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-46496dac"],{"2b1c":function(e,t,n){"use strict";n("dc36")},"44e73":function(e,t,n){"use strict";n.r(t);var a=n("c7eb"),c=(n("c346"),n("e63d")),r=n.n(c),o=n("1da1"),u=(n("b0c0"),n("7a23")),i=n("47e2"),l={class:"dev"},s={class:"view-title"},d={class:"view-container"},f={__name:"index",setup:function(e){var t=Object(i["b"])(),n=t.t,c=Object(u["ref"])(),f=Object(u["reactive"])({name:void 0}),b={name:{required:!0,message:"Please input name"}},m=function(){c.value.validate().then((function(){v(f.name)}))},p=Object(u["ref"])(!1),v=function(){var e=Object(o["a"])(Object(a["a"])().mark((function e(t){return Object(a["a"])().wrap((function(e){while(1)switch(e.prev=e.next){case 0:return p.value=!0,e.next=3,window.market.downloadPlugin({name:t,isDev:!0});case 3:r.a.success(n("feature.dev.installSuccess",{pluginName:t})),p.value=!1;case 5:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),j=function(){c.value.validate().then((function(){window.market.refreshPlugin({name:f.name}),r.a.success(n("feature.dev.refreshSuccess",{pluginName:f.name}))}))},O={span:4},w={span:14};return function(e,t){var n=Object(u["resolveComponent"])("a-alert"),a=Object(u["resolveComponent"])("a-input"),r=Object(u["resolveComponent"])("a-form-item"),o=Object(u["resolveComponent"])("a-button"),i=Object(u["resolveComponent"])("a-form");return Object(u["openBlock"])(),Object(u["createElementBlock"])("div",l,[Object(u["createElementVNode"])("div",s,Object(u["toDisplayString"])(e.$t("feature.dev.title")),1),Object(u["createElementVNode"])("div",d,[Object(u["createVNode"])(n,{style:{"margin-bottom":"40px"},message:e.$t("feature.dev.tips"),type:"warning"},null,8,["message"]),Object(u["createVNode"])(i,{ref_key:"formRef",ref:c,model:f,rules:b,"label-col":O,"wrapper-col":w},{default:Object(u["withCtx"])((function(){return[Object(u["createVNode"])(r,{label:e.$t("feature.dev.pluginName"),name:"name"},{default:Object(u["withCtx"])((function(){return[Object(u["createVNode"])(a,{value:f.name,"onUpdate:value":t[0]||(t[0]=function(e){return f.name=e})},null,8,["value"])]})),_:1},8,["label"]),Object(u["createVNode"])(r,{"wrapper-col":{span:14,offset:4}},{default:Object(u["withCtx"])((function(){return[Object(u["createVNode"])(o,{loading:p.value,type:"primary",onClick:m},{default:Object(u["withCtx"])((function(){return[Object(u["createTextVNode"])(Object(u["toDisplayString"])(e.$t("feature.dev.install")),1)]})),_:1},8,["loading"]),Object(u["createVNode"])(o,{onClick:j,style:{"margin-left":"10px"}},{default:Object(u["withCtx"])((function(){return[Object(u["createTextVNode"])(Object(u["toDisplayString"])(e.$t("feature.dev.refreshPlugins")),1)]})),_:1})]})),_:1})]})),_:1},8,["model"])])])}}},b=(n("2b1c"),n("6b0d")),m=n.n(b);const p=m()(f,[["__scopeId","data-v-2d26bea2"]]);t["default"]=p},a479:function(e,t,n){},c346:function(e,t,n){"use strict";n("fe5b"),n("a479")},dc36:function(e,t,n){}}]);

View File

@ -1 +0,0 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-5cf3b9db"],{"44e73":function(e,t,n){"use strict";n.r(t);var a=n("c7eb"),c=(n("c346"),n("e63d")),r=n.n(c),o=n("1da1"),u=(n("b0c0"),n("7a23")),i=n("47e2"),l={class:"dev"},s={class:"view-title"},f={class:"view-container"},d={__name:"index",setup:function(e){var t=Object(i["b"])(),n=t.t,c=Object(u["ref"])(),d=Object(u["reactive"])({name:void 0}),b={name:{required:!0,message:"Please input name"}},m=function(){c.value.validate().then((function(){v(d.name)}))},p=Object(u["ref"])(!1),v=function(){var e=Object(o["a"])(Object(a["a"])().mark((function e(t){return Object(a["a"])().wrap((function(e){while(1)switch(e.prev=e.next){case 0:return p.value=!0,e.next=3,window.market.downloadPlugin({name:t,isDev:!0});case 3:r.a.success(n("feature.dev.installSuccess",{pluginName:t})),p.value=!1;case 5:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),j=function(){c.value.validate().then((function(){window.market.refreshPlugin({name:d.name}),r.a.success(n("feature.dev.refreshSuccess",{pluginName:d.name}))}))},O={span:4},w={span:14};return function(e,t){var n=Object(u["resolveComponent"])("a-alert"),a=Object(u["resolveComponent"])("a-input"),r=Object(u["resolveComponent"])("a-form-item"),o=Object(u["resolveComponent"])("a-button"),i=Object(u["resolveComponent"])("a-form");return Object(u["openBlock"])(),Object(u["createElementBlock"])("div",l,[Object(u["createElementVNode"])("div",s,Object(u["toDisplayString"])(e.$t("feature.dev.title")),1),Object(u["createElementVNode"])("div",f,[Object(u["createVNode"])(n,{style:{"margin-bottom":"40px"},message:e.$t("feature.dev.tips"),type:"warning"},null,8,["message"]),Object(u["createVNode"])(i,{ref_key:"formRef",ref:c,model:d,rules:b,"label-col":O,"wrapper-col":w},{default:Object(u["withCtx"])((function(){return[Object(u["createVNode"])(r,{label:e.$t("feature.dev.pluginName"),name:"name"},{default:Object(u["withCtx"])((function(){return[Object(u["createVNode"])(a,{value:d.name,"onUpdate:value":t[0]||(t[0]=function(e){return d.name=e})},null,8,["value"])]})),_:1},8,["label"]),Object(u["createVNode"])(r,{"wrapper-col":{span:14,offset:4}},{default:Object(u["withCtx"])((function(){return[Object(u["createVNode"])(o,{loading:p.value,type:"primary",onClick:m},{default:Object(u["withCtx"])((function(){return[Object(u["createTextVNode"])(Object(u["toDisplayString"])(e.$t("feature.dev.install")),1)]})),_:1},8,["loading"]),Object(u["createVNode"])(o,{onClick:j,style:{"margin-left":"10px"}},{default:Object(u["withCtx"])((function(){return[Object(u["createTextVNode"])(Object(u["toDisplayString"])(e.$t("feature.dev.refreshPlugins")),1)]})),_:1})]})),_:1})]})),_:1},8,["model"])])])}}},b=(n("ef18"),n("6b0d")),m=n.n(b);const p=m()(d,[["__scopeId","data-v-6fb0031c"]]);t["default"]=p},a479:function(e,t,n){},c346:function(e,t,n){"use strict";n("fe5b"),n("a479")},ef18:function(e,t,n){"use strict";n("f44a")},f44a:function(e,t,n){}}]);

View File

@ -3,7 +3,7 @@
"pluginName": "系统菜单",
"description": "系统菜单",
"main": "index.html",
"logo": "https://pic1.zhimg.com/80/v2-c09780808301668a82e6646cb42f0806_720w.png",
"logo": "https://pic1.zhimg.com/80/v2-29152fe716010751db835adf591421f8_720w.png",
"version": "0.0.0",
"preload":"preload.js",
"pluginType": "ui",
@ -18,7 +18,7 @@
"code": "installed",
"explain": "已安装插件",
"cmds":[
"已安装插件"
"已安装插件", "installed"
]
},{
"code": "settings",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 131 KiB

BIN
public/icons/delete@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 845 B

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
public/icons/pin@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 B

BIN
public/icons/shield@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 828 B

BIN
public/icons/unpin@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 747 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 131 KiB

View File

@ -5,7 +5,7 @@ const path = require('path');
const appPath = app.getPath('userData');
const baseDir = path.join(appPath, './rubick-plugins');
const baseDir = path.join(appPath, './rubick-plugins-new');
const ipcSendSync = (type, data) => {
const returnValue = ipcRenderer.sendSync('msg-trigger', {
@ -49,6 +49,10 @@ window.rubick = {
showOpenDialog(options) {
return ipcSendSync('showOpenDialog', options);
},
showSaveDialog(options) {
return ipcSendSync('showSaveDialog', options);
},
setExpendHeight(height) {
ipcSendSync('setExpendHeight', height);
},

9
release.js Normal file
View File

@ -0,0 +1,9 @@
exports.default = async function () {
const fs = require('fs');
const compressing = require('compressing');
const src = './build/mac/rubick.app/Contents/Resources/app.asar';
if (fs.existsSync(src)) {
await compressing.gzip.compressFile(src, 'build/app.asar.gz');
}
};

View File

@ -1,5 +1,6 @@
export const WINDOW_WIDTH = 688;
export const WINDOW_WIDTH = 800;
export const WINDOW_HEIGHT = 60;
export const WINDOW_PLUGIN_HEIGHT = 600;
export const GUIDE_WIDTH = 800;
export const GUIDE_HEIGHT = 600;

View File

@ -1,5 +1,5 @@
export default {
version: 4,
version: 7,
perf: {
custom: {
theme: 'SPRING',
@ -25,6 +25,7 @@ export default {
autoPast: false,
darkMode: false,
guide: false,
history: true,
lang: 'zh-CN',
},
local: {

View File

@ -4,5 +4,6 @@ import path from 'path';
const appPath = app.getPath('userData');
const PLUGIN_INSTALL_DIR = path.join(appPath, './rubick-plugins-new');
const PLUGIN_HISTORY = 'rubick-plugin-history';
export { PLUGIN_INSTALL_DIR };
export { PLUGIN_INSTALL_DIR, PLUGIN_HISTORY };

View File

@ -9,7 +9,8 @@ const useDrag = () => {
let draggable = true;
const onMouseDown = (e) => {
// if (commonConst.macOS()) return;
// 右击不移动
if (e.button === 2) return;
draggable = true;
mouseX = e.clientX;
mouseY = e.clientY;

View File

@ -1,6 +1,6 @@
const WINDOW_MAX_HEIGHT = 600;
const WINDOW_MAX_HEIGHT = 620;
const WINDOW_MIN_HEIGHT = 60;
const PRE_ITEM_HEIGHT = 60;
const PRE_ITEM_HEIGHT = 70;
const HISTORY_HEIGHT = 70;
export default (searchList: Array<any>, historyList): number => {

View File

@ -32,63 +32,6 @@ const getIconFile = (appFileInput) => {
});
};
// const sortIcons = (icons) => {
// const aWins = -1;
// const bWins = 1;
// const catWins = 0;
// return icons.sort((a, b) => {
// const aSize = parseInt(a.match(/(\d+)x\1/)[1], 10);
// const bSize = parseInt(b.match(/(\d+)x\1/)[1], 10);
// if (aSize === bSize) {
// if (a.indexOf('@2x') > -1) return aWins;
// if (b.indexOf('@2x') > -1) return bWins;
// return catWins;
// }
// if (aSize > bSize) return aWins;
// if (aSize < bSize) return bWins;
// return catWins;
// });
// };
// const icnsToPng = (iconFile, pngFileOutput) => {
// const outputDir = pngFileOutput.split('.')[0] + '.iconset'
// return new Promise((resolve, reject) => {
// exec(`iconutil --convert iconset '${iconFile}' --output '${outputDir}'`, (error) => {
// if (error) return reject(error)
// fs.readdir(outputDir, (error, files) => {
// if (error) {
// return resolve(tiffToPng(iconFile, pngFileOutput))
// }
// const realIcons = files.map((file) => {
// return path.join(outputDir, file)
// })
// const biggestIcon = sortIcons(realIcons).find(Boolean)
// fs.rename(biggestIcon, pngFileOutput, (error) => {
// error ? reject(error) : resolve(realIcons.filter((file) => {
// return file !== biggestIcon
// }))
// })
// })
// })
// }).then((files) => {
// // Cleanup temp icons
// return Promise.all(files.map((file) => {
// return new Promise((resolve, reject) => {
// fs.unlink(file, (error) => {
// error ? reject(error) : resolve()
// })
// })
// }))
// }).then(() => {
// // Cleanup temp directory
// return new Promise((resolve, reject) => {
// fs.rmdir(outputDir, (error) => {
// error ? reject(error) : resolve()
// })
// })
// })
// }
const tiffToPng = (iconFile, pngFileOutput) => {
return new Promise((resolve, reject) => {
exec(

View File

@ -1,23 +1,23 @@
import { spawn } from "child_process";
import plist from "plist";
import { spawn } from 'child_process';
import plist from 'plist';
export default function getApps(resolve, reject, filterByAppName = false) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
let resultBuffer = new Buffer.from([]);
const profileInstalledApps = spawn("/usr/sbin/system_profiler", [
"-xml",
"-detailLevel",
"mini",
"SPApplicationsDataType",
const profileInstalledApps = spawn('/usr/sbin/system_profiler', [
'-xml',
'-detailLevel',
'mini',
'SPApplicationsDataType',
]);
profileInstalledApps.stdout.on("data", (chunckBuffer) => {
profileInstalledApps.stdout.on('data', (chunckBuffer) => {
resultBuffer = Buffer.concat([resultBuffer, chunckBuffer]);
});
profileInstalledApps.on("exit", (exitCode) => {
profileInstalledApps.on('exit', (exitCode) => {
if (exitCode !== 0) {
reject([]);
return;
@ -37,7 +37,7 @@ export default function getApps(resolve, reject, filterByAppName = false) {
}
});
profileInstalledApps.on("error", (err) => {
profileInstalledApps.on('error', (err) => {
reject(err);
});
}

View File

@ -1,12 +1,8 @@
import fs from 'fs';
import path from 'path';
import os from 'os';
import translate from './translate';
import { shell } from 'electron';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const fileIcon = require('extract-file-icon');
const filePath = path.resolve(
'C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs'
);
@ -29,6 +25,8 @@ if (!exists) {
const getico = (app) => {
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const fileIcon = require('extract-file-icon');
const buffer = fileIcon(app.desc, 32);
const iconpath = path.join(icondir, `${app.name}.png`);

View File

@ -7,11 +7,10 @@ import path from 'path';
import got from 'got';
import fixPath from 'fix-path';
import spawn from 'cross-spawn';
import { ipcRenderer } from 'electron';
import axios from 'axios';
import npm from 'npm';
fixPath();
/**
@ -42,7 +41,7 @@ class AdapterHandler {
}
this.baseDir = options.baseDir;
let register = options.registry || 'https://registry.npmmirror.com/';
let register = options.registry || 'https://registry.npmmirror.com';
try {
const dbdata = ipcRenderer.sendSync('msg-trigger', {
@ -61,7 +60,7 @@ class AdapterHandler {
const packageJSON = JSON.parse(
fs.readFileSync(`${this.baseDir}/package.json`, 'utf-8')
);
const registryUrl = `https://registry.npm.taobao.org/${name}`;
const registryUrl = `https://registry.npmmirror.com/${name}`;
// 从npm源中获取依赖包的最新版本
try {
@ -158,67 +157,44 @@ class AdapterHandler {
*/
private async execCommand(cmd: string, modules: string[]): Promise<string> {
return new Promise((resolve: any, reject: any) => {
const module =
let args: string[] = [cmd].concat(
cmd !== 'uninstall' && cmd !== 'link'
? modules.map((m) => `${m}@latest`)
: modules;
const config: any = {
prefix: this.baseDir,
save: true,
cache: path.join(this.baseDir, 'cache'),
};
: modules
);
if (cmd !== 'link') {
config.registry = this.registry;
args = args
.concat('--color=always')
.concat('--save')
.concat(`--registry=${this.registry}`);
}
npm.load(config, function (err) {
npm.commands[cmd](module, function (er, data) {
if (!err) {
console.log(data);
resolve({ code: -1, data });
} else {
reject({ code: -1, data: err });
}
});
npm.on('log', function (message) {
// log installation progress
console.log(message);
});
const npm = spawn('npm', args, {
cwd: this.baseDir,
});
// if (cmd !== 'link') {
// args = args
// .concat('--color=always')
// .concat('--save')
// .concat(`--registry=${this.registry}`);
// }
console.log(args);
// const npm = spawn('npm', args, {
// cwd: this.baseDir,
// });
//
// console.log(args);
//
// let output = '';
// npm.stdout
// .on('data', (data: string) => {
// output += data; // 获取输出日志
// })
// .pipe(process.stdout);
//
// npm.stderr
// .on('data', (data: string) => {
// output += data; // 获取报错日志
// })
// .pipe(process.stderr);
//
// npm.on('close', (code: number) => {
// if (!code) {
// resolve({ code: 0, data: output }); // 如果没有报错就输出正常日志
// } else {
// reject({ code: code, data: output }); // 如果报错就输出报错日志
// }
// });
let output = '';
npm.stdout
.on('data', (data: string) => {
output += data; // 获取输出日志
})
.pipe(process.stdout);
npm.stderr
.on('data', (data: string) => {
output += data; // 获取报错日志
})
.pipe(process.stderr);
npm.on('close', (code: number) => {
if (!code) {
resolve({ code: 0, data: output }); // 如果没有报错就输出正常日志
} else {
reject({ code: code, data: output }); // 如果报错就输出报错日志
}
});
});
}
}

View File

@ -54,6 +54,7 @@ export default () => {
executeHooks('PluginOut', null);
});
createWin.on('closed', () => {
view.webContents?.destroy();
win = undefined;
});
createWin.on('focus', () => {
@ -70,6 +71,7 @@ export default () => {
);
view.setAutoResize({ width: true, height: true });
createWin.setBrowserView(view);
view.inDetach = true;
createWin.webContents.executeJavaScript(
`window.initDetach(${JSON.stringify(pluginInfo)})`
);

View File

@ -3,6 +3,11 @@ import path from 'path';
import commonConst from '../../common/utils/commonConst';
import { PLUGIN_INSTALL_DIR as baseDir } from '@/common/constans/main';
import localConfig from '@/main/common/initLocalConfig';
import {
WINDOW_HEIGHT,
WINDOW_PLUGIN_HEIGHT,
WINDOW_WIDTH,
} from '@/common/constans/common';
const getRelativePath = (indexPath) => {
return commonConst.windows()
@ -57,8 +62,13 @@ export default () => {
const viewReadyFn = async (window, { pluginSetting, ext }) => {
if (!view) return;
const height = pluginSetting && pluginSetting.height;
window.setSize(800, height || 600);
view.setBounds({ x: 0, y: 60, width: 800, height: height || 540 });
window.setSize(WINDOW_WIDTH, height || WINDOW_PLUGIN_HEIGHT);
view.setBounds({
x: 0,
y: WINDOW_HEIGHT,
width: WINDOW_WIDTH,
height: height || WINDOW_PLUGIN_HEIGHT - WINDOW_HEIGHT,
});
view.setAutoResize({ width: true, height: true });
executeHooks('PluginEnter', ext);
executeHooks('PluginReady', ext);
@ -165,26 +175,29 @@ export default () => {
const removeView = (window: BrowserWindow) => {
if (!view) return;
window.removeBrowserView(view);
// window.setSize(800, 60);
executeHooks('PluginOut', null);
window.webContents?.executeJavaScript(`window.initRubick()`);
view = undefined;
setTimeout(() => {
window.removeBrowserView(view);
if (!view.inDetach) {
window.setBrowserView(null);
view.webContents?.destroy();
}
window.webContents?.executeJavaScript(`window.initRubick()`);
view = undefined;
}, 0);
};
const getView = () => view;
const executeHooks = (hook, data) => {
setTimeout(() => {
if (!view) return;
const evalJs = `if(window.rubick && window.rubick.hooks && typeof window.rubick.hooks.on${hook} === 'function' ) {
if (!view) return;
const evalJs = `if(window.rubick && window.rubick.hooks && typeof window.rubick.hooks.on${hook} === 'function' ) {
try {
window.rubick.hooks.on${hook}(${data ? JSON.stringify(data) : ''});
} catch(e) {}
}
`;
view.webContents?.executeJavaScript(evalJs);
}, 300);
view.webContents?.executeJavaScript(evalJs);
};
return {

View File

@ -26,6 +26,7 @@ import { runner, detach } from '../browsers';
import DBInstance from './db';
import getWinPosition from './getWinPosition';
import path from 'path';
import commonConst from '@/common/utils/commonConst';
const runnerInstance = runner();
const detachInstance = detach();
@ -97,7 +98,12 @@ class API extends DBInstance {
? 'http://localhost:8083/#/'
: `file://${__static}/tpl/index.html`;
}
if (!plugin.indexPath) {
if (plugin.name === 'rubick-system-feature') {
plugin.logo = plugin.logo || `file://${__static}/logo.png`;
plugin.indexPath = commonConst.dev()
? 'http://localhost:8081/#/'
: `file://${__static}/feature/index.html`;
} else if (!plugin.indexPath) {
const pluginPath = path.resolve(baseDir, 'node_modules', plugin.name);
plugin.indexPath = `file://${path.join(
pluginPath,
@ -122,8 +128,8 @@ class API extends DBInstance {
}
public removePlugin(e, window) {
this.currentPlugin = null;
runnerInstance.removeView(window);
this.currentPlugin = null;
}
public openPluginDevTools() {
@ -142,11 +148,24 @@ class API extends DBInstance {
return dialog.showOpenDialogSync(window, data);
}
public showSaveDialog({ data }, window) {
return dialog.showSaveDialogSync(window, data);
}
public setExpendHeight({ data: height }, window: BrowserWindow, e) {
const originWindow = this.getCurrentWindow(window, e);
if (!originWindow) return;
const targetHeight = height;
originWindow.setSize(originWindow.getSize()[0], targetHeight);
const screenPoint = screen.getCursorScreenPoint();
const display = screen.getDisplayNearestPoint(screenPoint);
const position =
originWindow.getPosition()[1] + targetHeight > display.bounds.height
? height - 60
: 0;
originWindow.webContents.executeJavaScript(
`window.setPosition && typeof window.setPosition === "function" && window.setPosition(${position})`
);
}
public setSubInput({ data }, window, e) {
@ -181,6 +200,7 @@ class API extends DBInstance {
value: data.text,
})})`
);
this.sendSubInputChangeEvent({ data });
}
public getPath({ data }) {
@ -191,11 +211,10 @@ class API extends DBInstance {
if (!Notification.isSupported()) return;
'string' != typeof body && (body = String(body));
const plugin = this.currentPlugin;
if (!plugin) return;
const notify = new Notification({
title: plugin.pluginName,
title: plugin ? plugin.pluginName : null,
body,
icon: plugin.logo,
icon: plugin ? plugin.logo : null,
});
notify.show();
}
@ -316,6 +335,7 @@ class API extends DBInstance {
shell.showItemInFolder(data.path);
return true;
}
public async getFileIcon({ data }) {
const nativeImage = await app.getFileIcon(data.path, { size: 'normal' });
return nativeImage.toDataURL();

View File

@ -10,15 +10,18 @@ import {
import screenCapture from '@/core/screen-capture';
import localConfig from '@/main/common/initLocalConfig';
import winPosition from './getWinPosition';
import { uIOhook, UiohookKey } from 'uiohook-napi';
const registerHotKey = (mainWindow: BrowserWindow): void => {
// 设置开机启动
const setAutoLogin = async () => {
const config = await localConfig.getConfig();
app.setLoginItemSettings({
openAtLogin: config.perf.common.start,
openAsHidden: true,
});
if (app.getLoginItemSettings().openAtLogin !== config.perf.common.start) {
app.setLoginItemSettings({
openAtLogin: config.perf.common.start,
openAsHidden: true,
});
}
};
const setTheme = async () => {
@ -55,27 +58,43 @@ const registerHotKey = (mainWindow: BrowserWindow): void => {
}
};
// 显示主窗口
function mainWindowPopUp() {
const currentShow = mainWindow.isVisible() && mainWindow.isFocused();
if (currentShow) return mainWindow.hide();
const { x: wx, y: wy } = winPosition.getPosition();
mainWindow.setAlwaysOnTop(false);
mainWindow.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
mainWindow.focus();
mainWindow.setVisibleOnAllWorkspaces(false, {
visibleOnFullScreen: true,
});
mainWindow.setPosition(wx, wy);
mainWindow.show();
}
const init = async () => {
await setAutoLogin();
await setDarkMode();
await setTheme();
const config = await localConfig.getConfig();
globalShortcut.unregisterAll();
// 注册偏好快捷键
globalShortcut.register(config.perf.shortCut.showAndHidden, () => {
const currentShow = mainWindow.isVisible() && mainWindow.isFocused();
if (currentShow) return mainWindow.hide();
const { x: wx, y: wy } = winPosition.getPosition();
mainWindow.setAlwaysOnTop(false);
mainWindow.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
mainWindow.focus();
mainWindow.setVisibleOnAllWorkspaces(false, {
visibleOnFullScreen: true,
});
mainWindow.setPosition(wx, wy);
mainWindow.show();
});
// 注册偏好快捷键
// 处理显示/隐藏快捷键的注册
const doublePressShortcuts = ['Ctrl+Ctrl', 'Option+Option', 'Shift+Shift', 'Command+Command'];
const isDoublePressShortcut = doublePressShortcuts.includes(config.perf.shortCut.showAndHidden);
if (isDoublePressShortcut) {
// 双击快捷键(如 Ctrl+Ctrl详见 uIOhookRegister 函数实现
} else {
// 注册普通快捷键(如 Ctrl+Space、F8 等)
globalShortcut.register(config.perf.shortCut.showAndHidden, () => {
mainWindowPopUp();
});
}
// 截图快捷键
globalShortcut.register(config.perf.shortCut.capture, () => {
screenCapture(mainWindow, (data) => {
data &&
@ -86,15 +105,22 @@ const registerHotKey = (mainWindow: BrowserWindow): void => {
});
});
// globalShortcut.register(config.perf.shortCut.separate, () => {
//
// });
globalShortcut.register(config.perf.shortCut.quit, () => {
// mainWindow.webContents.send('init-rubick');
// mainWindow.show();
});
// 添加局部快捷键监听
mainWindow.webContents.on('before-input-event', (event, input) => {
if (input.key.toLowerCase() === 'w'
&& (input.control || input.meta) && !input.alt && !input.shift) {
event.preventDefault();
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.hide();
}
}
});
// 注册自定义全局快捷键
config.global.forEach((sc) => {
if (!sc.key || !sc.value) return;
@ -103,9 +129,48 @@ const registerHotKey = (mainWindow: BrowserWindow): void => {
});
});
};
uIOhookRegister(mainWindowPopUp);
init();
ipcMain.on('re-register', () => {
init();
});
};
export default registerHotKey;
function uIOhookRegister(callback: () => void) {
let lastModifierPress = Date.now();
uIOhook.on('keydown', async (uio_event) => {
const config = await localConfig.getConfig(); // 此处还有优化空间
if (
![
'Ctrl+Ctrl',
'Option+Option',
'Shift+Shift',
'Command+Command',
].includes(config.perf.shortCut.showAndHidden)
) {
return;
}
// 双击快捷键,如 Ctrl+Ctrl
const modifers = config.perf.shortCut.showAndHidden.split('+');
const showAndHiddenKeyStr = modifers.pop(); // Ctrl
const keyStr2uioKeyCode = {
Ctrl: UiohookKey.Ctrl,
Shift: UiohookKey.Shift,
Option: UiohookKey.Alt,
Command: UiohookKey.Comma,
};
if (uio_event.keycode === keyStr2uioKeyCode[showAndHiddenKeyStr]) {
const currentTime = Date.now();
if (currentTime - lastModifierPress < 300) {
callback(); // 调用 mainWindowPopUp
}
lastModifierPress = currentTime;
}
});
uIOhook.start();
}

View File

@ -9,7 +9,7 @@ function createTray(window: BrowserWindow): Promise<Tray> {
return new Promise((resolve) => {
let icon;
if (commonConst.macOS()) {
icon = './icons/icon@3x.png';
icon = './icons/iconTemplate@2x.png';
} else if (commonConst.windows()) {
icon =
parseInt(os.release()) < 10

View File

@ -1,8 +1,5 @@
<template>
<div
id="components-layout"
@mousedown="onMouseDown"
>
<div id="components-layout" @mousedown="onMouseDown">
<Search
:currentPlugin="currentPlugin"
@changeCurrent="changeIndex"
@ -27,18 +24,24 @@
:currentSelect="currentSelect"
:options="options"
:clipboardFile="clipboardFile || []"
@setPluginHistory="setPluginHistory"
@choosePlugin="choosePlugin"
/>
</div>
</template>
<script setup lang="ts">
import { watch, ref, nextTick, toRaw } from 'vue';
import { ipcRenderer } from 'electron';
import { watch, ref, toRaw } from 'vue';
import { exec } from 'child_process';
import Result from './components/result.vue';
import Search from './components/search.vue';
import getWindowHeight from '../common/utils/getWindowHeight';
import createPluginManager from './plugins-manager';
import useDrag from '../common/utils/dragWindow';
import { getGlobal } from '@electron/remote';
import { PLUGIN_HISTORY } from '@/common/constans/renderer';
import { message } from 'ant-design-vue';
import localConfig from './confOp';
const { onMouseDown } = useDrag();
const remote = window.require('@electron/remote');
@ -60,6 +63,8 @@ const {
clearClipboardFile,
readClipboardContent,
pluginHistory,
setPluginHistory,
changePluginHistory,
} = createPluginManager();
initPlugins();
@ -67,6 +72,8 @@ initPlugins();
const currentSelect = ref(0);
const menuPluginInfo: any = ref({});
const config: any = ref(localConfig.getConfig());
getPluginInfo({
pluginName: 'feature',
// eslint-disable-next-line no-undef
@ -76,41 +83,35 @@ getPluginInfo({
remote.getGlobal('LOCAL_PLUGINS').addPlugin(res);
});
watch([options, pluginHistory, currentPlugin], () => {
currentSelect.value = 0;
// if (currentPlugin.value.name) return;
nextTick(() => {
ipcRenderer.sendSync('msg-trigger', {
type: 'setExpendHeight',
data: getWindowHeight(
watch(
[options, pluginHistory, currentPlugin],
() => {
currentSelect.value = 0;
if (currentPlugin.value.name) return;
window.rubick.setExpendHeight(
getWindowHeight(
options.value,
(pluginLoading.value || currentPlugin.value.name) ? [] : pluginHistory.value
),
});
});
});
pluginLoading.value || !config.value.perf.common.history
? []
: pluginHistory.value
)
);
},
{
immediate: true,
}
);
const changeIndex = (index) => {
if (!options.value.length) {
if (!pluginHistory.value.length) return;
if (
currentSelect.value + index > pluginHistory.value.length - 1 ||
currentSelect.value + index < 0
) {
currentSelect.value = 0;
return;
}
currentSelect.value = currentSelect.value + index;
return;
}
if (
currentSelect.value + index > options.value.length - 1 ||
currentSelect.value + index < 0
) {
const len = options.value.length || pluginHistory.value.length;
if (!len) return;
if (currentSelect.value + index > len - 1) {
currentSelect.value = 0;
return;
} else if (currentSelect.value + index < 0) {
currentSelect.value = len - 1;
} else {
currentSelect.value = currentSelect.value + index;
}
currentSelect.value = currentSelect.value + index;
};
const openMenu = (ext) => {
@ -125,13 +126,48 @@ const openMenu = (ext) => {
window.rubick.openMenu = openMenu;
const choosePlugin = () => {
const choosePlugin = (plugin) => {
if (options.value.length) {
const currentChoose = options.value[currentSelect.value];
currentChoose.click();
} else {
const currentChoose = pluginHistory.value[currentSelect.value];
currentChoose.click();
const localPlugins = getGlobal('LOCAL_PLUGINS').getLocalPlugins();
const currentChoose = plugin || pluginHistory.value[currentSelect.value];
let hasRemove = true;
if (currentChoose.pluginType === 'app') {
hasRemove = false;
changePluginHistory(currentChoose);
exec(currentChoose.action);
return;
}
localPlugins.find((plugin) => {
if (plugin.name === currentChoose.originName) {
hasRemove = false;
return true;
}
return false;
});
if (hasRemove) {
const result = window.rubick.db.get(PLUGIN_HISTORY) || {};
const history = result.data.filter(
(item) => item.originName !== currentChoose.originName
);
setPluginHistory(history);
return message.warning('插件已被卸载!');
}
changePluginHistory(currentChoose);
window.rubick.openPlugin(
JSON.parse(
JSON.stringify({
...currentChoose,
ext: {
code: currentChoose.feature.code,
type: currentChoose.cmd.type || 'text',
payload: null,
},
})
)
);
}
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,20 +1,30 @@
<template>
<div
v-show="!currentPlugin.name"
class="options"
ref="scrollDom"
>
<div class="history-plugins" v-if="!options.length || !(searchValue || !!clipboardFile.length)">
<div v-show="!currentPlugin.name" class="options">
<div
class="history-plugins"
v-if="
!options.length &&
!searchValue &&
!clipboardFile.length &&
config.perf.common.history
"
>
<a-row>
<a-col
@click="() => item.click()"
:class="currentSelect === index ? 'active history-item' : 'history-item'"
@click="() => openPlugin(item)"
@contextmenu.prevent="openMenu($event,item)"
:class="
currentSelect === index ? 'active history-item' : 'history-item'
"
:span="3"
v-for="(item, index) in pluginHistory"
:key="index"
>
<a-avatar style="width: 28px; height: 28px;" :src="item.icon" />
<div class="name ellpise">{{item.cmd || item.pluginName || item._name || item.name}}</div>
<a-avatar style="width: 28px; height: 28px" :src="item.icon" />
<div class="name ellpise">
{{ item.cmd || item.pluginName || item._name || item.name }}
</div>
<div class="badge" v-if="item.pin"></div>
</a-col>
</a-row>
</div>
@ -39,16 +49,17 @@
</template>
<script lang="ts" setup>
import BScroll from '@better-scroll/core';
import { defineProps, onMounted, ref } from 'vue';
import { defineEmits, defineProps, reactive, ref, toRaw, watch } from 'vue';
import localConfig from '../confOp';
const scrollDom = ref(null);
const path = window.require('path');
const remote = window.require('@electron/remote');
onMounted(() => {
new BScroll(scrollDom.value);
});
declare const __static: string;
const props = defineProps({
const config: any = ref(localConfig.getConfig());
const props: any = defineProps({
searchValue: {
type: [String, Number],
default: '',
@ -66,14 +77,22 @@ const props = defineProps({
clipboardFile: (() => [])(),
});
const emit = defineEmits(['choosePlugin', 'setPluginHistory']);
const renderTitle = (title, match) => {
if (typeof title !== 'string') return;
if (!props.searchValue || !match) return title;
const result = title.substring(match[0], match[1] + 1);
return `<div>${title.substring(0, match[0])}<span style='color: var(--ant-error-color)'>${result}</span>${title.substring(match[1]+1, title.length)}</div>`;
return `<div>${title.substring(
0,
match[0]
)}<span style='color: var(--ant-error-color)'>${result}</span>${title.substring(
match[1] + 1,
title.length
)}</div>`;
};
const renderDesc = (desc) => {
const renderDesc = (desc = '') => {
if (desc.length > 80) {
return `${desc.substr(0, 63)}...${desc.substr(
desc.length - 14,
@ -93,17 +112,97 @@ const sort = (options) => {
}
}
}
return options;
return options.slice(0, 20);
};
const openPlugin = (item) => {
emit('choosePlugin', item);
};
const menuState: any = reactive({
plugin: null,
});
let mainMenus;
const openMenu = (e, item) => {
const pinToMain = mainMenus.getMenuItemById('pinToMain');
const unpinFromMain = mainMenus.getMenuItemById('unpinFromMain');
pinToMain.visible = !item.pin;
unpinFromMain.visible = item.pin;
mainMenus.popup({
x: e.pageX,
y: e.pageY,
});
menuState.plugin = item;
};
const initMainCmdMenus = () => {
const menu = [
{
id: 'removeRecentCmd',
label: '从"使用记录"中删除',
icon: path.join(__static, 'icons', 'delete@2x.png'),
click: () => {
const history = props.pluginHistory.filter((item) => item.name !== menuState.plugin.name);
emit('setPluginHistory', toRaw(history));
},
},
{
id: 'pinToMain',
label: '固定到"搜索面板"',
icon: path.join(__static, 'icons', 'pin@2x.png'),
click: () => {
const history = props.pluginHistory.map((item) => {
if (item.name === menuState.plugin.name) {
item.pin = true;
}
return item;
});
emit('setPluginHistory', toRaw(history));
},
},
{
id: 'unpinFromMain',
label: '从"搜索面板"取消固定',
icon: path.join(__static, 'icons', 'unpin@2x.png'),
click: () => {
const history = props.pluginHistory.map((item) => {
if (item.name === menuState.plugin.name) {
item.pin = false;
}
return item;
});
emit('setPluginHistory', toRaw(history));
},
},
];
mainMenus = remote.Menu.buildFromTemplate(menu);
};
initMainCmdMenus();
</script>
<style lang="less">
.ellpise {
overflow:hidden;
text-overflow:ellipsis;
display:-webkit-box;
-webkit-line-clamp:1;
-webkit-box-orient:vertical;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
.contextmenu {
margin: 0;
background: #fff;
z-index: 3000;
position: absolute;
list-style-type: none;
padding: 5px 0;
border-radius: 4px;
font-size: 12px;
font-weight: 400;
color: #333;
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
}
.options {
@ -120,6 +219,7 @@ const sort = (options) => {
border-top: 1px dashed var(--color-border-light);
box-sizing: border-box;
.history-item {
cursor: pointer;
box-sizing: border-box;
height: 69px;
display: flex;
@ -128,6 +228,19 @@ const sort = (options) => {
flex-direction: column;
color: var(--color-text-content);
border-right: 1px dashed var(--color-border-light);
position: relative;
.badge {
position: absolute;
top: 2px;
right: 2px;
width: 0;
height: 0;
border-radius: 4px;
border-top: 6px solid var(--ant-primary-4);
border-right: 6px solid var(--ant-primary-4);
border-left: 6px solid transparent;
border-bottom: 6px solid transparent;
}
&.active {
background: var(--color-list-hover);
}
@ -141,7 +254,7 @@ const sort = (options) => {
}
.op-item {
padding: 0 10px;
height: 60px;
height: 70px;
line-height: 50px;
max-height: 500px;
overflow: auto;

View File

@ -25,6 +25,8 @@
ref="mainInput"
class="main-input"
@input="(e) => changeValue(e)"
@keydown.left="(e) => keydownEvent(e, 'left')"
@keydown.right="(e) => keydownEvent(e, 'right')"
@keydown.down="(e) => keydownEvent(e, 'down')"
@keydown.tab="(e) => keydownEvent(e, 'down')"
@keydown.up="(e) => keydownEvent(e, 'up')"
@ -41,10 +43,7 @@
>
<template #suffix>
<div class="suffix-tool">
<MoreOutlined
@click="showSeparate()"
class="icon-more"
/>
<MoreOutlined @click="showSeparate()" class="icon-more" />
</div>
</template>
</a-input>
@ -96,6 +95,7 @@ const emit = defineEmits([
]);
const keydownEvent = (e, key: string) => {
key !== 'space' && e.preventDefault();
const { ctrlKey, shiftKey, altKey, metaKey } = e;
const modifiers: Array<string> = [];
ctrlKey && modifiers.push('control');
@ -119,12 +119,19 @@ const keydownEvent = (e, key: string) => {
case 'down':
emit('changeCurrent', 1);
break;
case 'left':
emit('changeCurrent', -1);
break;
case 'right':
emit('changeCurrent', 1);
break;
case 'enter':
if (runPluginDisable) return;
emit('choosePlugin');
break;
case 'space':
if (runPluginDisable || !config.value.perf.common.space) return;
e.preventDefault();
emit('choosePlugin');
break;
default:

View File

@ -8,7 +8,10 @@ import commonConst from '@/common/utils/commonConst';
import { exec } from 'child_process';
import searchManager from './search';
import optionsManager from './options';
import { PLUGIN_INSTALL_DIR as baseDir } from '@/common/constans/renderer';
import {
PLUGIN_INSTALL_DIR as baseDir,
PLUGIN_HISTORY,
} from '@/common/constans/renderer';
import { message } from 'ant-design-vue';
const createPluginManager = (): any => {
@ -28,16 +31,22 @@ const createPluginManager = (): any => {
const appList: any = ref([]);
const initPlugins = async () => {
initPluginHistory();
appList.value = await appSearch(nativeImage);
initLocalStartPlugin();
};
const initPluginHistory = () => {
const result = window.rubick.db.get(PLUGIN_HISTORY) || {};
if (result && result.data) {
state.pluginHistory = result.data;
}
};
const initLocalStartPlugin = () => {
const result = ipcRenderer.sendSync('msg-trigger', {
type: 'dbGet',
data: {
id: 'rubick-local-start-app',
},
data: { id: 'rubick-local-start-app' },
});
if (result && result.value) {
appList.value.push(...result.value);
@ -68,17 +77,18 @@ const createPluginManager = (): any => {
};
const openPlugin = async (plugin, option) => {
ipcRenderer.send('msg-trigger', {
type: 'removePlugin',
});
window.initRubick();
if (plugin.pluginType === 'ui' || plugin.pluginType === 'system') {
if (state.currentPlugin && state.currentPlugin.name === plugin.name) {
ipcRenderer.sendSync('msg-trigger', {
type: 'showMainWindow',
});
window.rubick.showMainWindow();
return;
}
await loadPlugin(plugin);
ipcRenderer.sendSync('msg-trigger', {
type: 'openPlugin',
data: JSON.parse(
window.rubick.openPlugin(
JSON.parse(
JSON.stringify({
...plugin,
ext: plugin.ext || {
@ -87,8 +97,8 @@ const createPluginManager = (): any => {
payload: null,
},
})
),
});
)
);
}
if (plugin.pluginType === 'app') {
try {
@ -97,23 +107,55 @@ const createPluginManager = (): any => {
message.error('启动应用出错,请确保启动应用存在!');
}
}
window.initRubick();
changePluginHistory({
...plugin,
...option,
originName: plugin.name,
});
};
const changePluginHistory = (plugin) => {
state.pluginHistory.forEach((p, index) => {
if (p.name === plugin.name) {
state.pluginHistory.splice(index, 1);
}
});
state.pluginHistory.unshift(plugin);
if (state.pluginHistory.length > 8) {
state.pluginHistory.pop();
const unpin = state.pluginHistory.filter((plugin) => !plugin.pin);
const pin = state.pluginHistory.filter((plugin) => plugin.pin);
const isPin = state.pluginHistory.find((p) => p.name === plugin.name)?.pin;
if (isPin) {
pin.forEach((p, index) => {
if (p.name === plugin.name) {
plugin = pin.splice(index, 1)[0];
}
});
pin.unshift(plugin);
} else {
unpin.forEach((p, index) => {
if (p.name === plugin.name) {
unpin.splice(index, 1);
}
});
unpin.unshift(plugin);
}
if (state.pluginHistory.length > 8) {
unpin.pop();
}
state.pluginHistory = [...pin, ...unpin];
const result = window.rubick.db.get(PLUGIN_HISTORY) || {};
window.rubick.db.put({
_id: PLUGIN_HISTORY,
_rev: result._rev,
data: JSON.parse(JSON.stringify(state.pluginHistory)),
});
};
const setPluginHistory = (plugins) => {
state.pluginHistory = plugins;
const unpin = state.pluginHistory.filter((plugin) => !plugin.pin);
const pin = state.pluginHistory.filter((plugin) => plugin.pin);
state.pluginHistory = [...pin, ...unpin];
const result = window.rubick.db.get(PLUGIN_HISTORY) || {};
window.rubick.db.put({
_id: PLUGIN_HISTORY,
_rev: result._rev,
data: JSON.parse(JSON.stringify(state.pluginHistory)),
});
};
const { searchValue, onSearch, setSearchValue, placeholder } =
@ -206,6 +248,8 @@ const createPluginManager = (): any => {
clipboardFile,
clearClipboardFile,
readClipboardContent,
setPluginHistory,
changePluginHistory,
};
};

View File

@ -1,5 +1,5 @@
import { ref, watch } from 'vue';
import throttle from 'lodash.throttle';
import debounce from 'lodash.debounce';
import { ipcRenderer } from 'electron';
import { getGlobal } from '@electron/remote';
import PinyinMatch from 'pinyin-match';
@ -8,7 +8,7 @@ import useFocus from './clipboardWatch';
function formatReg(regStr) {
const flags = regStr.replace(/.*\/([gimy]*)$/, '$1');
const pattern = flags.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1');
const pattern = regStr.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1');
return new RegExp(pattern, flags);
}
@ -41,6 +41,17 @@ const optionsManager = ({
options[0].click();
});
const getIndex = (cmd, value) => {
let index = 0;
if (PinyinMatch.match(cmd.label || cmd, value)) {
index += 1;
}
if (cmd.label) {
index -= 1;
}
return index;
};
const getOptionsFromSearchValue = (value, strict = false) => {
const localPlugins = getGlobal('LOCAL_PLUGINS').getLocalPlugins();
let options: any = [];
@ -61,7 +72,7 @@ const optionsManager = ({
desc: fe.explain,
type: plugin.pluginType,
match: PinyinMatch.match(cmd.label || cmd, value),
zIndex: cmd.label ? 0 : 1, // 排序权重
zIndex: getIndex(cmd, value), // 排序权重
click: () => {
pluginClickEvent({
plugin,
@ -117,7 +128,7 @@ const optionsManager = ({
.map((plugin) => {
const option = {
...plugin,
zIndex: 1,
zIndex: 0,
click: () => {
openPlugin(plugin, option);
},
@ -130,7 +141,7 @@ const optionsManager = ({
watch(searchValue, () => search(searchValue.value));
// search Input operation
const search = throttle((value) => {
const search = debounce((value) => {
if (currentPlugin.value.name) return;
if (clipboardFile.value.length) return;
if (!value) {
@ -138,7 +149,7 @@ const optionsManager = ({
return;
}
optionsRef.value = getOptionsFromSearchValue(value);
}, 500);
}, 100);
const setOptionsRef = (options) => {
optionsRef.value = options;

View File

@ -33,6 +33,10 @@ module.exports = {
productName: 'rubick',
appId: 'com.muwoo.rubick',
compression: 'maximum',
// afterPack: './release.js',
// afterAllArtifactBuild: () => {
// return ['./build/app.asar.gz'];
// },
directories: {
output: 'build',
},

146
yarn.lock
View File

@ -1007,6 +1007,23 @@
ajv "^6.12.0"
ajv-keywords "^3.4.1"
"@eggjs/yauzl@^2.11.0":
version "2.11.0"
resolved "https://registry.yarnpkg.com/@eggjs/yauzl/-/yauzl-2.11.0.tgz#b8e4413f50fc7c51451f770f152de4c1137aa99b"
integrity sha512-Jq+k2fCZJ3i3HShb0nxLUiAgq5pwo8JTT1TrH22JoehZQ0Nm2dvByGIja1NYfNyuE4Tx5/Dns5nVsBN/mlC8yg==
dependencies:
buffer-crc32 "~0.2.3"
fd-slicer2 "^1.2.0"
"@electron/asar@^3.2.8":
version "3.2.8"
resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.2.8.tgz#2ea722f3452583dbd4ffdcc4b4f5dc903f1d8178"
integrity sha512-cmskk5M06ewHMZAplSiF4AlME3IrnnZhKnWbtwKVLRkdJkKyUVjMLhDIiPIx/+6zQWVlKX/LtmK9xDme7540Sg==
dependencies:
commander "^5.0.0"
glob "^7.1.6"
minimatch "^3.0.4"
"@electron/get@^2.0.0":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@electron/get/-/get-2.0.2.tgz#ae2a967b22075e9c25aaf00d5941cd79c21efd7e"
@ -3188,6 +3205,14 @@ bindings@^1.5.0:
dependencies:
file-uri-to-path "1.0.0"
bl@^1.0.0:
version "1.2.3"
resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7"
integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==
dependencies:
readable-stream "^2.3.5"
safe-buffer "^5.1.1"
bl@^4.1.0:
version "4.1.0"
resolved "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
@ -4280,6 +4305,21 @@ compressible@~2.0.16:
dependencies:
mime-db ">= 1.43.0 < 2"
compressing@^1.10.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/compressing/-/compressing-1.10.0.tgz#bca0f734736b5bb05c3a176fef8d60d7f5f322da"
integrity sha512-k2vpbZLaJoHe9euyUZjYYE8vOrbR19aU3HcWIYw5EBXiUs34ygfDVnXU+ubI41JXMriHutnoiu0ZFdwCkH6jPA==
dependencies:
"@eggjs/yauzl" "^2.11.0"
flushwritable "^1.0.0"
get-ready "^1.0.0"
iconv-lite "^0.5.0"
mkdirp "^0.5.1"
pump "^3.0.0"
streamifier "^0.1.1"
tar-stream "^1.5.2"
yazl "^2.4.2"
compression@^1.7.4:
version "1.7.4"
resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f"
@ -4829,7 +4869,7 @@ debug@^3.1.0, debug@^3.2.7:
dependencies:
ms "^2.1.1"
debuglog@*, debuglog@^1.0.1:
debuglog@^1.0.1:
version "1.0.1"
resolved "https://registry.npmmirror.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
integrity sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==
@ -6205,6 +6245,13 @@ faye-websocket@^0.11.3, faye-websocket@^0.11.4:
dependencies:
websocket-driver ">=0.5.1"
fd-slicer2@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/fd-slicer2/-/fd-slicer2-1.2.0.tgz#a2c54a540639bbcd4702480821771341277ca20e"
integrity sha512-3lBUNUckhMZduCc4g+Pw4Ve16LD9vpX9b8qUkkKq2mgDRLYWzblszZH2luADnJqjJe+cypngjCuKRm/IW12rRw==
dependencies:
pend "^1.2.0"
fd-slicer@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
@ -6387,6 +6434,11 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3"
readable-stream "^2.3.6"
flushwritable@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/flushwritable/-/flushwritable-1.0.0.tgz#3e328d8fde412ad47e738e3be750b4d290043498"
integrity sha512-3VELfuWCLVzt5d2Gblk8qcqFro6nuwvxwMzHaENVDHI7rxcBRtMCwTk/E9FXcgh+82DSpavPNDueA9+RxXJoFg==
follow-redirects@^1.0.0:
version "1.15.1"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5"
@ -6503,6 +6555,11 @@ from2@^2.1.0:
inherits "^2.0.1"
readable-stream "^2.0.0"
fs-constants@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
fs-extra@^10.0.0, fs-extra@^10.1.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
@ -6697,6 +6754,11 @@ get-mac-apps@^1.0.2:
dependencies:
plist "^3.0.1"
get-ready@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/get-ready/-/get-ready-1.0.0.tgz#f91817f1e9adecfea13a562adfc8de883ab34782"
integrity sha512-mFXCZPJIlcYcth+N8267+mghfYN9h3EhsDa6JSnbA3Wrhh/XFpuowviFcsDeYZtKspQyWyJqfs4O6P8CHeTwzw==
get-stdin@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b"
@ -7430,6 +7492,13 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.5:
dependencies:
safer-buffer ">= 2.1.2 < 3"
iconv-lite@^0.5.0:
version "0.5.2"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.5.2.tgz#af6d628dccfb463b7364d97f715e4b74b8c8c2b8"
integrity sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==
dependencies:
safer-buffer ">= 2.1.2 < 3"
iconv-lite@^0.6.2:
version "0.6.3"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
@ -7539,7 +7608,7 @@ import-local@^2.0.0:
pkg-dir "^3.0.0"
resolve-cwd "^2.0.0"
imurmurhash@*, imurmurhash@^0.1.4:
imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
@ -8842,11 +8911,6 @@ lodash-es@^4.17.15:
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
lodash._baseindexof@*:
version "3.1.0"
resolved "https://registry.npmmirror.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c"
integrity sha512-bSYo8Pc/f0qAkr8fPJydpJjtrHiSynYfYBjtANIgXv5xEf1WlTC63dIDlgu0s9dmTvzRu1+JJTxcIAHe+sH0FQ==
lodash._baseuniq@~4.6.0:
version "4.6.0"
resolved "https://registry.npmmirror.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8"
@ -8855,33 +8919,11 @@ lodash._baseuniq@~4.6.0:
lodash._createset "~4.0.0"
lodash._root "~3.0.0"
lodash._bindcallback@*:
version "3.0.1"
resolved "https://registry.npmmirror.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
integrity sha512-2wlI0JRAGX8WEf4Gm1p/mv/SZ+jLijpj0jyaE/AXeuQphzCgD8ZQW4oSpoN8JAopujOFGU3KMuq7qfHBWlGpjQ==
lodash._cacheindexof@*:
version "3.0.2"
resolved "https://registry.npmmirror.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92"
integrity sha512-S8dUjWr7SUT/X6TBIQ/OYoCHo1Stu1ZRy6uMUSKqzFnZp5G5RyQizSm6kvxD2Ewyy6AVfMg4AToeZzKfF99T5w==
lodash._createcache@*:
version "3.1.2"
resolved "https://registry.npmmirror.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093"
integrity sha512-ev5SP+iFpZOugyab/DEUQxUeZP5qyciVTlgQ1f4Vlw7VUcCD8fVnyIqVUEIaoFH9zjAqdgi69KiofzvVmda/ZQ==
dependencies:
lodash._getnative "^3.0.0"
lodash._createset@~4.0.0:
version "4.0.3"
resolved "https://registry.npmmirror.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"
integrity sha512-GTkC6YMprrJZCYU3zcqZj+jkXkrXzq3IPBcF/fIPpNEAB4hZEtXU8zp/RwKOvZl43NUmwDbyRk3+ZTbeRdEBXA==
lodash._getnative@*, lodash._getnative@^3.0.0:
version "3.9.1"
resolved "https://registry.npmmirror.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
integrity sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA==
lodash._root@~3.0.0:
version "3.0.1"
resolved "https://registry.npmmirror.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692"
@ -8894,7 +8936,7 @@ lodash.clonedeep@^4.5.0, lodash.clonedeep@~4.5.0:
lodash.debounce@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
resolved "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
lodash.defaultsdeep@^4.6.1:
@ -8937,16 +8979,6 @@ lodash.pick@^4.0.0:
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
integrity sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==
lodash.restparam@*:
version "3.6.1"
resolved "https://registry.npmmirror.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
integrity sha512-L4/arjjuq4noiUJpt3yS6KIKDtJwNe2fIYgMqyYYKoeIfV1iEqvPwhCx23o+R9dzouGihDAPN1dTIRWa7zk8tw==
lodash.throttle@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==
lodash.transform@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.transform/-/lodash.transform-4.6.0.tgz#12306422f63324aed8483d3f38332b5f670547a0"
@ -10513,7 +10545,7 @@ pbkdf2@^3.0.3:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
pend@~1.2.0:
pend@^1.2.0, pend@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==
@ -11542,7 +11574,7 @@ readable-stream@1.1.14, readable-stream@^1.0.27-1, readable-stream@~1.1.10:
isarray "0.0.1"
string_decoder "~0.10.x"
readable-stream@^2.0.6:
readable-stream@^2.0.6, readable-stream@^2.3.0, readable-stream@^2.3.5:
version "2.3.8"
resolved "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
@ -12739,6 +12771,11 @@ stream-shift@^1.0.0:
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
streamifier@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/streamifier/-/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f"
integrity sha512-zDgl+muIlWzXNsXeyUfOk9dChMjlpkq0DRsxujtYPgyJ676yQ8jEm6zzaaWHFDg5BNcLuif0eD2MTyJdZqXpdg==
strict-uri-encode@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
@ -12987,6 +13024,19 @@ tapable@^2.1.1, tapable@^2.2.0:
resolved "https://registry.npmmirror.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
tar-stream@^1.5.2:
version "1.6.2"
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555"
integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==
dependencies:
bl "^1.0.0"
buffer-alloc "^1.2.0"
end-of-stream "^1.0.0"
fs-constants "^1.0.0"
readable-stream "^2.3.0"
to-buffer "^1.1.1"
xtend "^4.0.0"
tar@^4.4.10, tar@^4.4.12, tar@^4.4.13:
version "4.4.19"
resolved "https://registry.npmmirror.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3"
@ -13182,6 +13232,11 @@ to-arraybuffer@^1.0.0:
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
integrity sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==
to-buffer@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
to-fast-properties@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
@ -14531,6 +14586,13 @@ yauzl@^2.10.0:
buffer-crc32 "~0.2.3"
fd-slicer "~1.1.0"
yazl@^2.4.2:
version "2.5.1"
resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35"
integrity sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==
dependencies:
buffer-crc32 "~0.2.3"
yorkie@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/yorkie/-/yorkie-2.0.0.tgz#92411912d435214e12c51c2ae1093e54b6bb83d9"