Flow Transfer API
Flow Transfer API
概述
Flow Transfer 是一个插件间数据流转系统,允许插件将结构化数据传递给其他插件进行处理。类似于移动端的"分享"功能,但更加强大和灵活。
介绍
Scope
本文档描述 当前已落地 的 Flow Transfer 基础能力:
- Sender:
dispatch()+ 选择目标面板 - Target:
onFlowTransfer()+acknowledge()/reportError() - Native Share:
nativeShare()
权限说明:Flow Transfer 已接入权限中心(Permission Center)与授权流程。未授权时会返回
PERMISSION_DENIED,并在选择面板触发授权弹窗。
v2.4.7 新特性:
- 插件需要主动注册
onFlowTransfer处理器才能接收 Flow 数据- 支持调用系统原生 Share 功能(macOS AirDrop、邮件、信息等)
- 目标列表按适配状态排序,未适配插件会显示提示
核心概念
Flow Payload(流转载荷)
发起插件提交的标准化数据包:
interface FlowPayload {
/** 载荷类型 */
type: 'text' | 'image' | 'files' | 'json' | 'html' | 'custom'
/** 主要数据内容 */
data: string | object
/** 数据的 MIME 类型(可选) */
mimeType?: string
/** 上下文元信息 */
context?: {
sourcePluginId: string
sourceFeatureId?: string
originalQuery?: TuffQuery
metadata?: Record<string, any>
}
}
当前实现说明:FlowTarget 的最终可用列表由主进程维护。
- Native share targets:由主进程在启动时注册。
- Plugin targets:当前通过主进程通道
flow:register-targets注册(由运行时/加载器负责触发)。 如果你发现 manifest 声明的 targets 没有出现在列表中,说明对应注册流程尚未覆盖到你的运行路径。
Flow Target(流转目标)
接收端在 manifest 中声明的可接收 Flow 的端点:
interface FlowTarget {
/** 目标唯一 ID(插件内唯一) */
id: string
/** 显示名称 */
name: string
/** 描述 */
description?: string
/** 支持的载荷类型 */
supportedTypes: ('text' | 'image' | 'files' | 'json' | 'html' | 'custom')[]
/** 图标(iconify 格式) */
icon?: string
/** 关联的 Feature ID */
featureId?: string
}
快捷键
Flow Transfer 提供两个全局快捷键(可在设置中自定义):
| 快捷键 | 功能 | 说明 |
|---|---|---|
Command/Ctrl+D | 分离到 DivisionBox | 将当前选中项分离到独立窗口 |
Command/Ctrl+Shift+D | Flow 流转 | 打开 Flow 选择面板,将数据发送到其他插件 |
插件配置
在 manifest.json 中声明 Flow 能力
Flow 的 manifest 配置结构以 FlowManifestConfig 为准:
flowSender?: booleanflowTargets?: FlowTarget[]
{
"name": "my-plugin",
"version": "1.0.0",
"flowSender": true,
"flowTargets": [
{
"id": "quick-note",
"name": "快速记录",
"description": "将内容保存为笔记",
"supportedTypes": ["text", "html", "image"],
"icon": "ri:sticky-note-line",
"featureId": "create-note"
},
{
"id": "translate",
"name": "翻译",
"description": "翻译选中的文本",
"supportedTypes": ["text"],
"icon": "ri:translate",
"featureId": "translate-text"
}
]
}
SDK 使用
发起 Flow(发送方)
import { createFlowSDK } from '@talex-touch/utils/plugin/sdk'
// 创建 Flow SDK 实例
const flow = createFlowSDK(channel, 'my-plugin-id')
// 发起流转
async function shareToOtherPlugin() {
const result = await flow.dispatch(
{
type: 'text',
data: 'Hello from my plugin!',
context: {
sourcePluginId: 'my-plugin-id',
metadata: { timestamp: Date.now() }
}
},
{
title: '分享文本',
description: '将文本发送到其他插件'
}
)
console.log('Flow result:', result.state)
}
// 直接发送到指定目标(跳过选择面板)
async function sendToSpecificTarget() {
const result = await flow.dispatch(
{
type: 'json',
data: { title: 'Note', content: 'Content...' }
},
{
preferredTarget: 'notes-plugin.quick-note',
skipSelector: true,
requireAck: true,
timeout: 10000,
fallbackAction: 'copy'
}
)
if (result.state === 'ACKED') {
console.log('Acknowledged:', result.ackPayload)
}
}
获取可用目标
// 获取所有可用目标
const allTargets = await flow.getAvailableTargets()
// 获取支持特定类型的目标
const textTargets = await flow.getAvailableTargets('text')
const imageTargets = await flow.getAvailableTargets('image')
接收 Flow(接收方)⚡ 重要
插件必须注册 onFlowTransfer 处理器才能接收 Flow 数据。 未注册的插件仍会在目标列表中显示,但会标记为"未适配"并排在列表末尾。
import { createFlowSDK } from '@talex-touch/utils/plugin/sdk'
const flow = createFlowSDK(channel, 'my-plugin-id')
// 注册 Flow 接收处理器(必需!)
const unsubscribe = flow.onFlowTransfer(async (payload, sessionId, sender) => {
console.log(`收到来自 ${sender.senderName} 的 ${payload.type} 数据`)
try {
// 处理数据
const result = await processPayload(payload)
// 发送确认
await flow.acknowledge(sessionId, { success: true, result })
} catch (error) {
// 报告错误
await flow.reportError(sessionId, error.message)
}
})
// 组件卸载时取消注册
onUnmounted(() => {
unsubscribe()
})
通过 Feature 触发(备选方式)
你也可以通过 Feature 的 query 参数接收 Flow 数据:
import { extractFlowData, isFlowTriggered } from '@talex-touch/utils/plugin/sdk'
function onFeatureTriggered(featureId: string, query: TuffQuery) {
// 检查是否通过 Flow 触发
if (isFlowTriggered(query)) {
const flowData = extractFlowData(query)
if (flowData) {
console.log('来自:', flowData.senderId)
console.log('类型:', flowData.payload.type)
console.log('数据:', flowData.payload.data)
// 处理 Flow 数据
processFlowPayload(flowData.sessionId, flowData.payload)
}
} else {
// 普通触发(非 Flow)
console.log('普通查询:', query.text)
}
}
发送确认响应
async function processFlowPayload(sessionId: string, payload: FlowPayload) {
try {
// 处理数据...
const result = await saveNote(payload.data)
// 发送确认
await flow.acknowledge(sessionId, {
success: true,
noteId: result.id,
message: '保存成功'
})
} catch (error) {
// 报告错误
await flow.reportError(sessionId, error.message)
}
}
Flow 会话状态
type FlowSessionState =
| 'INIT' // 初始化
| 'TARGET_SELECTING' // 用户选择目标中
| 'TARGET_SELECTED' // 目标已选择
| 'DELIVERING' // 投递中
| 'DELIVERED' // 已投递
| 'PROCESSING' // 目标处理中
| 'ACKED' // 已确认完成
| 'FAILED' // 失败
| 'CANCELLED' // 已取消
错误处理
enum FlowErrorCode {
SENDER_NOT_ALLOWED = 'SENDER_NOT_ALLOWED',
TARGET_NOT_FOUND = 'TARGET_NOT_FOUND',
TARGET_OFFLINE = 'TARGET_OFFLINE',
PAYLOAD_INVALID = 'PAYLOAD_INVALID',
PAYLOAD_TOO_LARGE = 'PAYLOAD_TOO_LARGE',
TYPE_NOT_SUPPORTED = 'TYPE_NOT_SUPPORTED',
PERMISSION_DENIED = 'PERMISSION_DENIED',
TIMEOUT = 'TIMEOUT',
CANCELLED = 'CANCELLED',
INTERNAL_ERROR = 'INTERNAL_ERROR'
}
原生系统分享
Flow Transfer 集成了系统原生分享功能,可以将数据分享到 AirDrop、邮件、信息等系统应用。
使用原生分享
const flow = createFlowSDK(channel, 'my-plugin-id')
// 使用系统分享
const result = await flow.nativeShare({
type: 'text',
data: 'Hello World!'
})
// 指定分享目标
const result = await flow.nativeShare(
{ type: 'text', data: 'Hello!' },
'airdrop' // 可选: 'system' | 'airdrop' | 'mail' | 'messages'
)
if (result.success) {
console.log('分享成功:', result.target)
} else {
console.error('分享失败:', result.error)
}
支持的原生目标
| 平台 | 目标 | 说明 |
|---|---|---|
| macOS | system | 系统分享面板 |
| macOS | airdrop | AirDrop |
| macOS | mail | 邮件 |
| macOS | messages | 信息 (iMessage) |
| Windows | system | Windows 分享 |
| Windows | mail | 邮件 |
目标排序规则
Flow 目标列表按以下优先级排序:
- 原生分享目标 - 系统分享功能优先显示
- 已适配插件 - 注册了
onFlowTransfer处理器的插件 - 未适配插件 - 未注册处理器的插件(显示"未适配"提示)
// FlowTargetInfo 中的适配状态字段
interface FlowTargetInfo {
// ...其他字段
hasFlowHandler: boolean // 是否已注册处理器
isNativeShare?: boolean // 是否为原生分享目标
adaptationHint?: string // 适配提示(如"该插件尚未适配 Flow Transfer")
}
IPC 通道(实现对齐)
以下通道是当前实现中使用到的关键事件名(详见主进程 apps/core-app/src/main/modules/flow-bus/):
flow:dispatch:发起 flowflow:get-targets:获取可用 targetsflow:cancel:取消 sessionflow:acknowledge:ackflow:report-error:上报错误flow:session-update:广播 session 状态更新flow:select-target:用户在选择面板选中 target(UI → 主进程)flow:native-share:系统分享
插件集成(主进程侧注册):
flow:register-targets:注册 targets(plugin → 主进程)flow:unregister-targets:卸载 targetsflow:set-plugin-enabled:更新 plugin enabled 状态flow:set-plugin-handler:声明当前插件是否已注册onFlowTransferhandler
技术原理
- Flow Transfer 在主进程维护目标列表与路由,负责权限校验与能力匹配。
- Sender/Target 通过标准化 payload 进行交换,避免插件间耦合。
最佳实践
- 注册 onFlowTransfer:始终注册处理器以获得最佳用户体验
- 声明支持的类型:在 manifest 中准确声明
supportedTypes,避免接收无法处理的数据 - 提供有意义的名称:Flow 目标的
name和description会显示在选择面板中 - 及时响应:收到 Flow 后尽快调用
acknowledge或reportError - 处理超时:设置合理的
timeout,并提供fallbackAction - 验证数据:接收方应验证 payload 数据的完整性和有效性
相关文档
- DivisionBox API - 独立窗口系统
- Plugin Manifest - 插件配置