API v1
Documentation/开发指南

提供按钮预设

为常用动作提供默认名称、图标和状态外观。

Plugin API v1

Documentation content is currently available in Simplified Chinese.

好的体验往往藏在细节里。当用户在飞块中为一个物理按键添加功能时,如果能“一步到位”,开箱自带精美的图标、贴切的标题和合理的默认参数,这种省心感会让你的插件格外受欢迎。

**按钮预设(Button Preset)**正是为此而生。它就像一套开箱即用的模板:用户从菜单中拖出一个预设按键,即可自动绑定好动作与视觉外观;当然,在创建完成后,用户依然可以自由微调。


#1. 绑定动作与默认外观

在 manifest.json 的 contributes.buttonPresets 数组中添加预设项,将 actionId 指向你在插件中实现的动作 ID,并在 button 中定制初始视觉:

json
{
  "contributes": {
    "buttonPresets": [
      {
        "id": "hello-button",
        "title": "问候按钮",
        "actionId": "hello",
        "button": {
          "title": "打个招呼",
          "icon": {
            "kind": "emoji",
            "text": "👋"
          }
        }
      }
    ]
  }
}

💡 清单组织提示:上面的代码片段基于创建第一个插件中的 hello 动作。在实际项目中,只需将 buttonPresets 追加到已有清单中,原有的动作声明依然完整保留。


#2. 动态生成按键名称(titleFrom)

在许多实用工具中,固定的标题显得过于呆板。例如,“启动应用程序”按键如果能自动显示为“微信”或“Photoshop”,体验就会流畅得多。

飞块支持通过 button.titleFrom 让宿主根据用户填写的特定参数动态推导按键名称:

  • 从参数智能解析:例如配置 titleFrom: "application-name" 时,飞块会自动解析用户选中的本地应用路径或可执行文件名,提取出精简美观的软件名称;
  • 从文本模板填充:结合用户输入的变量格式化按钮标题。

📚 深入参考:更多支持的动态转换模式与图标格式(如内置 Emoji、官方矢量图标库及自定义 SVG),请参阅 ButtonAppearance 参考文档。


#3. 根据实时状态切换外观与动作(多状态按键)

对于开关类设备(如静音切换、麦克风静音、智能插座等),我们通常希望按键能够真实反映当前设备状态,并能在点击时触发相反的操作。

如果你的插件已发布了全局枚举状态(详见发布状态),预设可以通过 multiState.sourceId 订阅该来源,为不同的状态值定义专属的外观与点击动作。官方的“状态开关”示例正是如此实现的:

json
{
  "apiVersion": 1,
  "id": "example.state-button",
  "name": "状态按钮",
  "version": "1.0.0",
  "description": "状态按钮教学示例",
  "hostPlatforms": [
    "windows",
    "macos",
    "linux"
  ],
  "main": "index.js",
  "permissions": [],
  "contributes": {
    "actions": [
      {
        "id": "enable",
        "title": "开启",
        "argsSchema": {
          "type": "object",
          "properties": {},
          "required": [],
          "additionalProperties": false
        },
        "outputSchema": {
          "type": "object",
          "properties": {
            "status": {
              "type": "string"
            }
          },
          "required": [
            "status"
          ],
          "additionalProperties": false
        },
        "titleKey": "actions.enable.title"
      },
      {
        "id": "disable",
        "title": "关闭",
        "argsSchema": {
          "type": "object",
          "properties": {},
          "required": [],
          "additionalProperties": false
        },
        "outputSchema": {
          "type": "object",
          "properties": {
            "status": {
              "type": "string"
            }
          },
          "required": [
            "status"
          ],
          "additionalProperties": false
        },
        "titleKey": "actions.disable.title"
      }
    ],
    "stateSources": [
      {
        "id": "status",
        "title": "开关状态",
        "description": "教学开关,不修改实际系统静音",
        "scope": "global",
        "visibility": "global",
        "readAccess": {
          "workflows": true,
          "widgets": true
        },
        "writeAccess": "owner-plugin",
        "lifetime": "plugin",
        "schema": {
          "type": "string",
          "enum": [
            "on",
            "off"
          ],
          "enumLabels": [
            "已开启",
            "已关闭"
          ]
        },
        "titleKey": "stateSources.status.title",
        "descriptionKey": "stateSources.status.description"
      }
    ],
    "buttonPresets": [
      {
        "id": "switch",
        "title": "教学状态开关",
        "actionId": "enable",
        "button": {
          "title": "开关",
          "icon": {
            "kind": "emoji",
            "text": "💡"
          },
          "size": "1x1",
          "titleKey": "buttonPresets.switch.button.title"
        },
        "multiState": {
          "sourceId": "status",
          "states": [
            {
              "id": "on",
              "actionId": "disable",
              "button": {
                "title": "已开启",
                "icon": {
                  "kind": "emoji",
                  "text": "💡"
                },
                "titleKey": "buttonPresets.switch.multiState.states.on.button.title"
              }
            },
            {
              "id": "off",
              "actionId": "enable",
              "button": {
                "title": "已关闭",
                "icon": {
                  "kind": "emoji",
                  "text": "💤"
                },
                "titleKey": "buttonPresets.switch.multiState.states.off.button.title"
              }
            },
            {
              "id": "unknown",
              "button": {
                "title": "等待状态",
                "icon": {
                  "kind": "none"
                },
                "titleKey": "buttonPresets.switch.multiState.states.unknown.button.title"
              }
            }
          ]
        },
        "titleKey": "buttonPresets.switch.title"
      }
    ]
  },
  "i18n": {
    "defaultLocale": "zh-CN",
    "resources": {
      "zh-CN": "locales/zh-CN.json",
      "en-US": "locales/en-US.json"
    }
  },
  "nameKey": "plugin.name",
  "descriptionKey": "plugin.description"
}

状态联动逻辑剖析:

  1. 状态为 on 时:按键视觉高亮并显示“关闭”;按下该按键将触发 disable 动作。
  2. 动作生效后:后台逻辑发布状态为 off,按键界面立即自动响应并变更为“开启”;下次按下则触发 enable 动作。
  3. 未就绪兜底(unknown):在插件刚启动或外部硬件连接尚未就绪时,状态处于未知阶段。预设通过 unknown 状态展示等待图标或灰度提示,让用户清晰分辨“当前正在加载中”与“设备已关闭”。

🔍 本地轮换按键:如果你的按键不需要读取外部硬件状态,仅仅是用户每按一下在本地循环切换(例如在 3 种预设模式间轮转),可使用无需后台的本地多状态模式。详细配置请参阅 MultiState 清单参考。

Updated 2026-11-04
View implementation sources