自动化

使用预设或自己的规则,在输入时调整键盘,而不替换已保存的设置。

状态规则会在条件满足期间应用临时设置。你可以组合屏幕方向、窗口宽度、外观、语言、布局、输入框属性、时间或插件声明的状态,并选择需要满足所有条件还是任一条件。未知上下文不会被视为满足否定条件。

事件规则会在键盘打开、语言或输入框属性改变、插件发出事件,或你轻点快捷方式时运行。每个事件只执行一次命令。设置覆盖会持续到键盘关闭、规则更改,或你清除本次会话的覆盖设置。

已保存的设置始终是基础

规则叠加在当前已保存的设置上。拖动可更改优先级,靠后的规则优先。关闭规则会移除它带来的更改。临时覆盖结束后,你保存的修改仍然有效。配置文件操作是临时的,不会选择或重写已保存的配置文件。

紧凑预设在现有尺寸限制内,将按键行高设为 28 点,宽度设为已保存宽度的 80%。启用分体后,较小的按键会在两半之间留出更多空间,同时让两半靠近边缘。单手模式保留自己的对齐方式。百分比始终以保存值为基准,不会反复累积。

预览使用你选择的示例上下文,在不执行命令的情况下显示满足的条件、无效引用和预期设置。应用内的预览与实际运行的键盘无关。将“自动化”添加到顶部栏,即可查看生效的覆盖设置并运行快捷规则。

事件发生时

事件发生时

  • keyboard.open
  • keyboard.close
  • keyboard.languageChanged
  • keyboard.layoutChanged
  • keyboard.profileChanged
  • keyboard.planeChanged
  • input.changed
  • time.minute
  • user.run

操作

  • panel.close
  • plane.letters
  • plane.numbers
  • plane.symbols
  • overrides.clear
  • panel.emoji
  • panel.calculator
  • panel.conversion
  • panel.layouts
  • panel.profiles

条件仅在键盘处于活动状态时评估。时间规则不会在后台运行,关闭事件也不保证触发。Clink 无法识别宿主应用或更改 iOS 设置。规则仍须满足所用功能对会员、完全访问和用户轻点的要求。导入不会授予任何权限。

插件契约

.clinkplugin 文件中的可选 automation 对象声明事件、状态、设置、命令、预设和快捷槽位。每项功能都有稳定的 ID、必须精确匹配的架构版本和本地化标题。宿主生成 plugin/<plugin-id>/<kind>/<id> 格式的名称。插件不能占用核心或其他插件的命名空间。

发布的状态、事件数据和命令参数支持布尔值、有范围限制的数值和已声明的选项。设置还可使用长度受限的文本。状态和设置使用插件现有状态字典中的键。临时值会在保存前恢复。预设是普通的已关闭规则,需要用户明确选择。

插件 ›

钩子

钩子调用时机
on_automation(command, args, state)on_automation(command, args, state) 在现有沙盒中运行获准的本地命令。它可以更新空格键文字、发布已声明的状态或发出已声明的事件。此钩子不允许插入文本、访问剪贴板、永久更改设置或发出外部请求。
automation_emit(name, payload)发出已声明的事件及其带类型的数据。宿主会补充插件命名空间和架构版本;脚本不能自行提供用户手势或执行链的历史信息。
automation_publish(name, value)发布一个供条件使用的已声明状态值。键盘会话结束或插件不可用时,这些值会消失。
automation_run(slot)从插件原生控件的操作处理函数中调用。用户在“自动化”中将已声明的快捷槽位映射到规则。插件不能悄悄替用户选择规则,也不能通过定时器触发需要轻点的命令。

操作

  • space_text
  • automation_emit
  • automation_publish

已声明的事件与安全命令

此清单片段放在普通插件文件的 automation 字段中。脚本会发布键盘是否就绪,发出事件并更新文字。在编辑器中选择该事件,要求 ready 状态,然后选择 caption 命令。阅读此示例不会安装或启用任何插件。

{
  "schemaVersion": 1,
  "events": [
    {
      "id": "ready",
      "title": {
        "en": "Keyboard ready"
      },
      "version": 1,
      "payload": [
        {
          "id": "ready",
          "key": "ready",
          "title": {
            "en": "Ready"
          },
          "version": 1,
          "type": "bool",
          "choices": [],
          "minimum": 0,
          "maximum": 100,
          "defaultValue": null
        }
      ]
    }
  ],
  "state": [
    {
      "id": "ready",
      "key": "ready",
      "title": {
        "en": "Ready"
      },
      "version": 1,
      "type": "bool",
      "choices": [],
      "minimum": 0,
      "maximum": 100,
      "defaultValue": null
    }
  ],
  "settings": [
    {
      "id": "show_caption",
      "key": "show_caption",
      "title": {
        "en": "Show caption"
      },
      "version": 1,
      "type": "bool",
      "choices": [],
      "minimum": 0,
      "maximum": 100,
      "defaultValue": true
    }
  ],
  "commands": [
    {
      "id": "caption",
      "title": {
        "en": "Refresh caption"
      },
      "version": 1,
      "arguments": [],
      "behavior": "localUI",
      "requiresUserGesture": false,
      "requiresFullAccess": false
    }
  ],
  "presets": [],
  "shortcuts": [
    "run"
  ]
}
def initial():
    return {"ready": False, "show_caption": True}

def on_open(state):
    state["ready"] = True
    automation_publish("ready", True)
    automation_emit("ready", {"ready": True})
    return state

def on_automation(command, args, state):
    if command == "caption":
        space_text("Clink" if state["show_caption"] else None)
    return state

def bar_items(state):
    return [bar_button("run", "Run automation", icon="bolt.circle")]

def on_action(action, value, state):
    if action == "run":
        automation_run("run")
    return state

确认内容后再分享规则

在“自动化”中导入和导出 JSON。导入的规则默认关闭,会获得新的标识,并保留对主题、布局和插件的引用。缺失的引用必须恢复后,规则才能运行。规则全局有效,也可限定到某个配置文件;它们与配置文件导出和 iCloud 同步分开保存。

{
  "schemaVersion": 1,
  "shortcutBindings": {},
  "rules": [
    {
      "id": "landscape-split",
      "name": "Landscape split",
      "enabled": false,
      "schemaVersion": 1,
      "kind": "state",
      "trigger": "keyboard.open",
      "triggerVersion": 1,
      "cooldownSeconds": 1,
      "conditions": {
        "mode": "all",
        "items": [
          {
            "id": "landscape",
            "field": "interface.orientation",
            "comparison": "equals",
            "value": "landscape",
            "upper": null,
            "hysteresis": 0,
            "version": 1
          }
        ]
      },
      "actions": [
        {
          "id": "split",
          "kind": "set",
          "target": "layout.split",
          "value": true,
          "version": 1
        }
      ]
    }
  ]
}

架构与限制

版本 1 支持 128 条规则,每条规则最多 24 个条件、32 个操作,导入大小不超过 1,048,576 字节。设置注册表提供 268 个目标,并记录 39 项排除项。无效的配置组会整体被拒绝;命令在首次失败时停止,不承诺撤销之前的效果。

插件功能被删除、禁用或变为不兼容时,依赖它的规则将不可用。崩溃和超时会在本次会话中禁用出错的功能。命令最多运行 20,000 步,并有较短的时间限制。队列上限、执行间隔、链长度限制和状态稳定机制可防止事件无限重复执行。

小组件

Clink 带有三个主屏幕小组件和一个实时活动:配置文件切换器、你的打字统计、快速听写,以及听写会话本身。

小组件直接读取共享的设置文件,所以应用关着也照常工作。

App Intents

目前有两个 intent,都不会打开应用。Switch Keyboard Profile 从小组件改写共享设置,已经显示在屏幕上的键盘会立刻跟上。End Dictation 从实时活动触达麦克风会话,必要时在后台启动应用。

切换到你自己做的配置文件需要会员,这项检查在小组件内部同样执行。Clink 自带的配置文件是免费的。

Clink 没有定义自己的快捷指令短语,所以没有可以念出来的命令。

打开文件

Clink 已向 iOS 登记自己的文件类型,所以“文件”、隔空投送、“信息”和任何分享单都会提供用 Clink 打开。

在 App Store 下载