事件与 Channel

事件系统让后端与前端双向通信:前端可以监听后端发出的任意命名事件, 也可以向前端/其他窗口定向发送。监听器注册表位于后端的 EventManager, API 由 @zturnlibs/ztron-apievent 模块提供。

listen / once / emit / emitTo

真实签名(摘自 packages/api/src/event.ts):

export async function listen<T>(
  event: string,
  handler: EventCallback<T>,
  options?: Options,
): Promise<UnlistenFn>;

export type UnlistenFn = () => Promise<void>;

典型用法:

import { listen, once, emit, emitTo } from "@zturnlibs/ztron-api";

// 监听(options.target 可指定窗口 label,默认 { kind: "Any" })
const unlisten = await listen<{ n: number }>("m3:tick", (e) => {
  console.log(e.payload.n); // e: { event, id, payload }
});
await unlisten(); // 不再需要时取消监听

// 只触发一次,触发后自动取消
await once("app:ready", () => console.log("ready"));

// 向后端发事件(后端会扇出给所有监听者)
await emit("frontend:poke", { at: Date.now() });

// 定向发送到指定窗口
await emitTo("main", "broadcast:x", { v: 1 });

窗口事件名

packages/api/src/window.tsWindowEventName 完整列表(原样):

export type WindowEventName =
  | "resize"
  | "move"
  | "focus"
  | "blur"
  | "close-requested"
  | "suspended"
  | "resumed"
  | "scale-change"
  | "theme-changed"
  | "drag-enter"
  | "drag-over"
  | "drag-drop"
  | "drag-leave";

其中 suspended/resumed 是为移动端生命周期保留的名字,桌面 host 不会触发;drag-* 四项对应文件拖放(ztron://drag-enter/over/drop/leave)。 event.ts 还导出了 ZtronEvent 常量枚举(上游 TauriEvent 的对应物; 如 ZtronEvent.WINDOW_RESIZED = "ztron://resize"),窗口实例上也提供 onResized/onMoved/onScaleChanged/onThemeChanged/onDragDropEvent 等便捷方法。

Channel:流式数据

一次性 invoke 只能返回单值;需要后端持续推送时,在命令参数里传入 { kind: "channel", id },后端经 ctx.getChannel(id) 拿到句柄后 handle.send(...) 多次推送、handle.end() 收尾——hello 示例的 m3:stream 命令即此模式(M1_EVENTS_CHANNEL_WINDOW_OK 已验证)。

插件监听器

插件侧还有一条 plugin:*|__listener 契约(如 log 插件把日志推给 webview 目标),P2 的插件页会展开。

适用版本:ztron 0.3.1