实现工具自由!开源的桌面工具箱

news/2024/11/28 20:53:58/

在一切开始之前,首先要致敬 uTools!如果没有它就没有 Rubick。

大家好,我是“拉比克”(Rubick)项目的作者木偶。我做的 Rubick 是一款基于 Electron 的开源桌面工具箱,简单讲就是好多工具的集合,然后加上快速启动、丰富的插件扩展等功能于一体。

没错!它的使用方式和外观几乎和 uTools 一摸一样。那我为什么放着免费的 uTools 不用,非要自己搞一个呢?

事情的起因是这样的,出于安全方面的考虑有一些仅适用于公司内部的插件不能发布到插件市场,所以不能接入 uTools。但实在眼馋 uTools 式的便捷、用完即走的极简操作体验。在搜寻解决方案无果,同时也发现其他的小伙伴也有同样的诉求,所以我动手做了,然后把它开源了。

Rubick 一款呼出超快、用完即走的开源工具箱,因为开源所以更自由!

项目地址:https://github.com/clouDr-f2e/rubick

希望它能帮助你解决同样的烦恼,但目前仅支持 Windows 和 macOS,Linux 版本正在开发中。想借助开源的力量让 Rubick 变强,成为金牌辅助!帮助大家轻松“超神”!

在做 Rubick 的过程中还是遇到了不少问题和挑战,下面就分享下我的心路历程。

一、缘起

1.1 初识 Electron

Electron 是 GitHub 开源的一个框架。它通过 Node.js 和 Chromium 的渲染引擎完成跨平台的桌面 GUI 应用程序的开发。我起初没有接触过 Electron,最开始接触它是因为看到了 PicGo 的一个核心功能非常吸引我,就是 macOS 下可以直接拖拽图片进入任务托盘上传图片:

当时正好我们团队也需要搞一个内部的 CDN 图片资源管理图床,用于项目图片资源压缩并直接上传到 CDN 上,之前我们做了个网页版。而这里我深刻的感受到了 Electron 的强大,可以极大的提高工作效率,参考 PicGo 我尝试做了第一个 Electron 项目,完成了图片压缩上传到内部 CDN 的桌面端应用。

1.2 演化

之后公司内部因为开发和后端进行接口联调测试环境时,经常会涉及到一些状态改变要看交互样式的问题。比如测试需要测商品的待支付、支付中、支付完成等各种节点的交互样式是否符合预期,这种情况测试一般会去造数据或者让后端改数据库接口。有的小伙伴可能会用 Charles 修改返回数据进行测试,但 Charles 的抓包体验和配置体验感觉有点麻烦,对新人不是很友好所以我们自己做了个非常易用 抓包&mock 工具:

这也是 Rubick 最早的雏形。随后,我们发现当页面发布线上的时候,没有办法在微信环境内对线上页面进行调试,所以开发了一个基于 winner 的远程调试功能。

但随着该 Rubick 在内部不断推广和使用,所需功能也越来越多。我们需要 需求管理、性能评估、埋点检测 等等工具。这些工具的增加一方面导致 Rubick 体积暴增,一方面又导致了用户需要不断更新软件,导致用户体验非常差。

其次,我们在推广给测试、UI 同学使用的时候,发现他们其实并不关注前面的页面调试、性能测评等功能,可能只是用到其中某一项,所以整个项目对他们来说就显得很臃肿。

1.3 灵感

直到有一天,我在掘金上看到这样一个沸点:

下面有个评论提到了 uTools 这是我第一次和 uTools 产生了交集,在体验了 uTools 功能后,我长吸一口气:这不就是我想要的嘛!然后就去 GitHub 上找 uTools 的源码,发现它并没有开源。

所以就想把上面提到的那些工具, 发布到 uTools 市场在 uTools 里通过插件的方式使用他们。但我发现发布插件只能发布到公网,但这又涉及到数据安全的问题。

无奈,难道真的要自己做一个这样的工具吗?真的是有点头大。不过想想也挺有意思的。至此,我萌生了要开发一个媲美 uTools 的开源工具箱的念头。

二、研发

开篇第一步,按照我之前的套路都是先取好名字先占个坑。我是个 Dota 玩家,之前写了一本《从0开始可视化搭建》的小册,里面使用了 Dota 中一个英雄的名字 coco(船长)。这次我取名的是 rubick 即 拉比克。Rubick(拉比克) 也是 Dota 里面的英雄之一,其核心技能是插件化使用其他英雄的技能,用完即走。非常符合本工具的设计理念,所以取名 Rubick。

我的核心目标就是需要让 Rubick 支持插件化,解决前面提到的问题:

  • 每个人的工具箱不同

  • 软件体积暴增

  • 每增加一个工具就需要更新版本

其次,通过调研了解到团队内有些同学已经在使用 uTools 了,要想让他们从 uTools 上把插件零成本迁移到 Rubick 上,就必须实现 uTools 的部分 API 能力,以及插件的定义和写法也需要和 uTools 规范保持一致。

2.1 开发者模式

插件开发需要和 Rubick 进行联调,所以 Rubick 需要支持开发者模式,帮助开发者更好的开发插件。首先先建一个 plugin.json 用于描述插件的基础信息:

{"pluginName": "测试插件","author": "muwoo","description": "我的第一个 rubick 插件","main": "index.html","version": "0.0.2","logo": "logo.png","name": "rubick-plugin-demo","gitUrl": "","features": [{"code": "hello","explain": "这是一个测试的插件","cmds":["hello222", "你好"]}],"preload": "preload.js"
}

2.1.1 核心字段

  • name 插件仓库名称

  • pluginName 插件名称

  • description 插件描述,简洁的说明这个插件的作用

  • main 入口文件,如果没有定义入口文件,此插件将变成一个模版插件

  • version 插件的版本,用于版本更新提示

  • features 插件核心功能列表

  • features.code 插件某个功能的识别码,可用于区分不同的功能

  • features.cmds 通过哪些方式可以进入这个功能

2.1.2 示例

开发插件的方式是复制 plugin.json 进入到 Rubick 的搜索框,所以需要监听搜索框的 change 事件,用于读取当前剪切板复制的内容:

onSearch ({ commit }, paylpad) {// 获取剪切板复制的文件路径const fileUrl = clipboard.read('public.file-url').replace('file://', '');// 如果是复制 plugin.json 文件if (fileUrl && value === 'plugin.json') {// 读取 json 文件const config = JSON.parse(fs.readFileSync(fileUrl, 'utf-8'));// 生成插件配置const pluginConfig = {...config,// 记录 index.html 存方的路径sourceFile: path.join(fileUrl, `../${config.main || 'index.html'}`),id: uuidv4(),// 标记为开发者type: 'dev',// 读取 iconicon: 'image://' + path.join(fileUrl, `../${config.logo}`),// 标记是否是模板subType: (() => {if (config.main) {return ''}return 'template';})()};}
}

到这里我们已经可以根据复制的 plugin.json 能获取到插件的最基础的信息,接下来就是需要展示搜索框:

 commit('commonUpdate', {options: [{name: '新建rubick开发插件',value: 'new-plugin',icon: 'https://xxx.com/img.png',desc: '新建rubick开发插件',click: (router) => {commit('commonUpdate', {showMain: true,selected: {key: 'plugin',name: '新建rubick开发插件'},current: ['dev'],});ipcRenderer.send('changeWindowSize-rubick', {height: getWindowHeight(),});router.push('/home/dev')}},{name: '复制路径',desc: '复制路径',value: 'copy-path',icon: 'https://xxx.com/img.png',click: () => {clipboard.writeText(fileUrl);commit('commonUpdate', {showMain: false,selected: null,options: [],});ipcRenderer.send('changeWindowSize-rubick', {height: getWindowHeight([]),});remote.Notification('Rubick 通知', { body: '复制成功' });}}]
});

到这里,当复制 plugin.json 进入搜索框时,便可直接出现 2 个选项,一个新建插件,一个复制路径的功能:

当点击 新建 rubick 插件 功能时,则需要跳转到 home 页,加载插件的基础内容,唯一需要注意的是 home 页加载的内容高度应该是 Rubick 最大窗口的高度。所以需要调整窗口大小:

 ipcRenderer.send('changeWindowSize-rubick', {height: getWindowHeight(),});

关于 renderer 里面的 Vue 代码这里就不再详细介绍了,因为大多是 css 画一下就好了,直接来看展示界面:

到这里,就完成了开发者模式,接下来再聊聊插件是如何在 Rubick 中跑起来的。

2.3 插件运行原理

运行插件需要容器 Electron 提供了一个 webview 的容器来加载外部网页。所以可以借助 webview 的能力实现动态网页渲染,这里所谓的网页就是插件。但是网页无法使用 node 的能力,而且做插件的目的就是为了开放与约束,需要对插件开放一些内置的 API 能力。好在 webview 提供了一个 preload 的能力,可以在页面加载的时候去预置一个脚本来执行。

也就是说可以给自己的插件写一个 preload.js 来加载。但这里需要注意既要保持插件的个性又得向插件内注入全局 API 供插件使用,所以可以直接加载 Rubick 内置 preload.js,在 preload.js 内再加载个性化的 preload.js

// webview plugin.vue
<webview id="webview" :src="path" :preload="preload"></webview>
<script>
export default {name: "index.vue",data() {return {path: `File://${this.$route.query.sourceFile}`,// 加载当前 static 目录中的 preload.jspreload: `File://${path.join(__static, './preload.js')}`,webview: null,query: this.$route.query,config: {},}}
}
</script>

对于 preload.js 就可以这么用啦:

if (location.href.indexOf('targetFile') > -1) {filePath = decodeURIComponent(getQueryVariable('targetFile'));
} else {filePath = location.pathname.replace('file://', '');
}window.utools = {// utools 所有的 api 实现
}
// 加载插件 preload.js
require(path.join(filePath, '../preload.js'));

到这里就已经实现了一个最基础的插件加载,效果如下:

2.4 支持更多体验能力

随后为了更加贴近 uTools 的体验,我又开始着手让 Rubick 支持更多原生体验增强的特性:超级面板、模板、系统命令、全局快捷键等

三、最后

再次致敬 uTools!我做 Rubick 旨在技术分享,并不以商业化为目的。

以上就是我和 Rubick 的故事,如果 Rubick 对您有帮助,那么就请给个 Star ✨ 鼓励一下:

https://github.com/clouDr-f2e/rubick


机缘巧合我发现了 HelloGitHub 一个推荐开源项目的平台,了解到卤蛋也是喜欢打 Dota,我想那他应该能感受到 Rubick 的魅力,所以我就抱着试一试的心态投稿了。先是有幸入选了月刊第 64 期,然后受邀写了这篇关于 Rubick 的故事。

最后,感谢 HelloGitHub 让 Rubick 被更多人发现和喜欢,特别感谢卤蛋对文章的润色和修改,让本文增色不少。

???? 关注「HelloGitHub」第一时间收到更新????


http://www.ppmy.cn/news/545986.html

相关文章

windows下的多桌面的小工具

windows下的多桌面的小工具&#xff0c;还可以隐藏程序图标

windows桌面小工具(Tkinter)

一. 小工具功能 数据加解密&#xff08;blowfish&#xff09;json格式化获取字符串md5base64解码url解码获取文件md5 二.小工具的实现 界面实现 def makeico():# 窗口左上角图标src "ico图标的base编码"data src.split(,)[1]image_data base64.b64decode(data…

【win】WINDOWS10系统自带桌面整理工具

最近强迫症又犯了&#xff0c;所有东西全丢在桌面&#xff0c;感觉桌面乱糟糟的&#xff0c;但是又不想下一堆没用的什么XX桌面整理工具&#xff0c;恰好看到一篇文写的就是win10自带的桌面整理&#xff0c;超级好用&#xff0c;特此记录下来。 #1-> 新建一个文件夹&#x…

Qt桌面工具包

目录 一、注册登录功能 1、头文件&#xff1a;form.h。功能实现主要引用数据库保存用户信息&#xff0c;同时使用QPaintEvent事件和QPainter画家来实现。 2、form.cpp实现功能代码 3、效果 二、闹钟功能 2、form1.cpp文件&#xff0c;实现功能 3、效果 三、垃圾狗 设计…

[160]八款最佳的远程桌面工具

远程桌面是微软公司为了方便网络管理员管理维护服务器而推出的一项服务。从windows 2000 server版本开始引入&#xff0c;网络管理员使用远程桌面连接程序连接到网络任意一台开启了远程桌面控制功能的计算机上&#xff0c;就好比自己操作该计算机一样&#xff0c;运行程序&…

八款最佳的远程桌面工具

八款最佳的远程桌面工具 作者&#xff1a;chszs&#xff0c;转载需注明。博客主页&#xff1a;http://blog.csdn.net/chszs 远程桌面是微软公司为了方便网络管理员管理维护服务器而推出的一项服务。从windows 2000 server版本开始引入&#xff0c;网络管理员使用远程桌面连接程…

推荐5款Windows桌面效率工具

今天我想分享一些自己比较喜欢的桌面端软件&#xff0c;还请大家包涵指正。如果你曾搜索过 Windows 效率工具推荐&#xff0c;对下文的软件或许有所了解。不过为了凑字数&#xff0c;我还是会再介绍一遍。 1.文件定位——Listary Listary 是我使用频率最高的软件之一&#xf…

使用鲁棒优化的定价策略进行微电网不平衡管理研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…