QQ扫一扫联系
FocusAny 是一个专注高效的AI工具条,可以使用 Alt / Option+空格 一键唤起,通过插件快速安装,可以扩展出非常多的功能。
目前支持 Windows、MacOS、Linux 系统。
创建一个文件夹,写入以下几个文件,即可完成一个最简单的插件开发。
config.json
index.html
logo.png
config.json
{
"name": "MyPlugin",
"title": "我的插件",
"description": "这是一个测试插件",
"version": "1.0.0",
"logo": "logo.png",
"main": "index.html",
"actions": [
{
"name": "default",
"type": "web",
"matches": [ "我的插件" ]
}
]}
index.html
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <h1>hello world</h1> </body> </html>
logo.png
准备一个你喜欢的图片,重命名为 logo.png,尺寸为 128x128 放入到插件目录中。
插件管理 → 选择本地目录插件 ,选择刚刚创建的插件目录。
在 FocusAny 中输入 我的插件,即可看到刚刚创建的插件。
这样,一个最简单的插件就开发完成了 🎉🎉🎉
随后,你可以使用前端技术开发更丰富的功能,插件的每部分功能说明可以参考详细的配置。
开发好的插件目录应该包含所有已打包好的资源文件(包括 js、css、图片等)。
如果使用的是 vue、react 等框架,请在插件管理中重新添加打包目录(如 dist 或 build)验证插件是否正常。
① 在 focusany.com注册账号
② 进入到个人中心,完成实名认证 focusany.com/member_cer
进入到 用户中心 → 开发的插件 页面,添加一个新的插件,填写插件的相关信息。
插件创建完成后,创建一个新的版本,上传插件的压缩包,等待审核通过后即可发布。
审核完成后,插件进入预发布状态,需要手动点击发布按钮,即可成功发布到插件市场。
{
// 插件定义 schema,可以方便输入提示和校验
"$schema": "https://focusany.com/sdk/config.schema.json",
// 插件名称,整个平台唯一,格式为大写驼峰命名
"name": "BasicExample",
// 插件版本,格式为 主版本号.次版本号.修订版本号
// 主版本号:功能大的升级
// 次版本号:日常迭代功能更新
// 修订版本号:修复 bug
"version": "1.0.0",
// 插件标题,显示在插件列表中
"title": "示例插件",
// 插件作者
"author": "focusany",
// 插件主页
"homepage": "https://focusany.com",
// 插件说明
"description": "示例插件说明",
// 插件主页面
"main": "index.html",
// 插件快捷面板主页面
"mainFastPanel": "fastpanel.html",
// 插件 logo,尺寸为 128x128,相对于插件目录
"logo": "logo.svg",
// 插件预加载文件,相对于插件目录
"preload": "preload.cjs",
// 插件支持的平台,不填写则支持所有平台
"platforms": [
"win",
"mac",
"linux"
],
// 插件依赖的软件版本,如 * 或 >=1.0.0 或 <=1.0.0 或 >1.0.0 或 <1.0.0,此为选填,留空表示不限制 FocusAny 版本。
"versionRequire": "*",
// 插件动作配置
"actions": [
// 打开插件(使用文本匹配)
{
"name": "text-simple",
"title": "使用text匹配(简单)",
"matches": [
"example-text-simple"
]
},
// 打开插件(使用文本匹配)
{
"name": "text",
"title": "使用text匹配",
"matches": [
{
"type": "text",
"minLength": 1,
"maxLength": 10,
"text": "example-text"
}
]
},
// 打开插件(使用key匹配)
{
"name": "key",
"title": "使用key匹配",
"matches": [
{
"type": "key",
"key": "example"
}
]
},
// 打开插件(使用正则匹配)
{
"name": "regex",
"title": "使用正则匹配",
"matches": [
{
"type": "regex",
"regex": "/example/"
}
]
},
// 打开插件(使用文件匹配)
{
"name": "file",
"title": "使用文件匹配(文件)",
"matches": [
{
"type": "file",
"minCount": 1,
"maxCount": 10,
"filterFileType": "file",
"filterExtensions": [
"xlsx",
"png"
]
}
]
},
// 打开插件(使用文件匹配)
{
"name": "file-directory",
"title": "使用文件匹配(文件夹)",
"matches": [
{
"type": "file",
"minCount": 1,
"maxCount": 10,
"filterFileType": "directory"
}
]
},
// 打开插件(使用窗口匹配)
{
"name": "window",
"title": "使用窗口匹配",
"matches": [
{
"type": "window",
"nameRegex": "/iTerm2/"
},
{
"type": "window",
"titleRegex": "/Electron/"
},
{
"type": "window",
"attrRegex": {
"url": "/github.com/"
}
}
]
},
// 打开插件(使用图片匹配)
{
"name": "image",
"title": "使用图片匹配",
"matches": [
{
"type": "image"
}
]
},
// 执行render代码
{
"name": "code",
"title": "使用code匹配(简单)",
"type": "code",
"matches": [
"example-code"
]
},
// 执行后台代码
{
"name": "backend",
"title": "使用backend匹配(简单)",
"type": "backend",
"matches": [
"example-backend"
]
},
// 执行命令
{
"name": "command",
"title": "执行一个命令",
"type": "command",
"matches": [
"example-command"
],
"data": {
"command": "notepad.exe"
}
},
// 自定义渲染
{
"name": "view",
"title": "显示view",
"type": "view",
"matches": [
{
"type": "regex",
"regex": "/^\\s*[a-zA-Z0-9]+\\s*$/"
}
]
},
// 编辑器匹配
{
"name": "editor",
"title": "使用editor匹配",
"matches": [
{
"type": "editor",
"faDataTypes": [
"FileEditorExample"
]
}
]
}
],
// 插件设置
"setting": {
// 插件是否打开即自动分离,默认为 false
"autoDetach": false,
// 分离模式默认位置,可选 center left-top left-bottom right-top right-bottom
"detachPosition": "center",
// 分离模式默认是否置顶
"detachAlwaysOnTop": false,
// 默认高度,支持 数字 或 百分比,设置后窗口大小将默认为分离模式
"height": "600",
// 默认宽度,支持 数字 或 百分比,设置后窗口大小将默认为分离模式
"width": "800",
// 快速面板高度,单位为像素,默认为 100
"heightFastPanel": 100,
// 是否只允许打开一个窗口,默认为 true
"singleton": true,
// 窗口默认缩放比例,100表示原始大小
"zoom": 100
},
// 开发配置
"development": {
// 开发环境,prod 表示生产环境,dev 表示开发环境,prod 环境会忽略 development 的所有配置。
"env": "prod",
// 入口文件,当该配置为空时,表示插件应用为模板插件应用。 main 与 preload 至少存在其一。
"main": "http://localhost:8080",
// 快速面板入口文件,当该配置为空时,使用主入口文件。
"mainFastPanel": "http://localhost:8080/fastpanel.html"
}}
系统会打开一个窗口,加载插件的 main 页面。
系统会打开一个渲染窗口,但是不会显示这个窗口,同时执行 preload.cjs 中定义的代码,比如在 preload.cjs 中定义了 plugin-example-code,那么在插件中就可以执行这个动作。
window.exports = {
"code": {
"plugin-example-code": async (data) => {
console.log('plugin-example-code', data);
}
}
}
系统会在主进程执行 preload 定义的代码。
系统会在主进程执行 data.command 定义的命令。
系统会在快捷面板中渲染该视图。
使用简单的文字匹配,包括拼音、简写等。
使用严格的匹配规则,只有完全匹配才会触发。
使用正则表达式匹配,可以匹配更复杂的规则。
使用图片匹配,可以匹配图片中的内容。
使用文件匹配,可以匹配文件的类型、扩展名等。
使用窗口匹配,可以匹配窗口的标题、名称、属性等。
使用编辑器匹配,用户主动打开某个类型的文件可以触发。
在浏览器开发时,是禁止执行一些本地操作的(比如读取文件、执行系统命令等),但是在插件中,我们可以通过 preload.cjs 文件来执行这些操作。
比如将以下代码写入到 preload.cjs 文件中,即可在插件中读取文件。
const fs = require("fs");window.myFocusAnyApi = {
readFile(path) {
return fs.readFileSync(path, "utf8");
},};
一个完整的 backend.cjs 文件示例:
module.exports = {
"hook": {
"installed": async (focusany) => {
focusany.showToast('插件已安装')
},
"beforeUninstall": async (focusany) => {
focusany.showToast('插件即将卸载')
},
},
"event": {
"testEvent": async (focusany, data) => {
console.log('testEvent.focusany', focusany);
console.log('testEvent.data', data);
focusany.showToast('事件已触发');
return "data from backend : " + JSON.stringify(data)
}
},
"action": {
"plugin-example-backend": async (focusany, data) => {
console.log('plugin-example-backend.focusany', focusany);
console.log('plugin-example-backend.data', data);
// console.log('test', await focusany.showSaveDialog());
focusany.showToast('后台进程已执行');
return 'ok'
}
}}
随后在插件的页面中,就可以通过 window.myFocusAnyApi.readFile 函数来读取文件。
本示例代码已经上传到 Gitee 和 Github,可以直接根据地址查看。
Gitee 地址:https://gitee.com/modstart-lib/focusany-plugin-example
Github 地址:https://github.com/modstart-lib/focusany-plugin-example
原生 HTML、CSS、JS 开发,无任何框架,可以查看到最基础的插件开发方式。
基于 vue3 + vite + tailwindcss 开发的基础文件编辑器,可以使用很轻量的方式集成一些文件编辑器。
基于 vue3 + vite + tailwindcss 开发的插件示例,可以查看到如何使用 vue3 开发插件。