@virid/main
v0.3.3
Published
Electron main process adapter for Virid, responsible for sending, receiving, and broadcasting rendering process messages
Readme
@virid/main
@virid/main 是electron应用的主适配器,提供ToRendererMessage和FromRendererMessage的自动路由功能与接受渲染进程报道功能。
🌟 核心设计理念
在 @virid/main 中,主进程朝渲染进程发送消息被抽象为ToRendererMessage,该消息可以直接通过调度器分发,消息将会通过IPC直接传送到渲染进程并触发对应的System。渲染进程朝主进程发送的消息被抽象为FromRendererMessage,一旦渲染进程发送了对应的消息,FromRendererMessage将会自动被投递到调度器触发相应的主进程System。
- 路由自动注册:渲染进程窗口开启后,自动向主进程注册自身,以后所有的消息都将携带自身的窗口信息。
- 类型恢复:消息在通过IPC通道后,恢复成真正的Message类重新进入
@virid/core并被调度器识别并分发。实现不同进程的位置无关性。 - 消息定向与广播:可以通过其他渲染进程的ID来实现定向通信,或者使用“*”来广播消息。
🔌启用插件
import { createVirid } from "@virid/core";
import { MainPlugin } from "@virid/main";
import { app } from "electron";
const virid = createVirid().use(MainPlugin, { electronApp: app });🛠️ @virid/main 核心 API 概览
ToRendererMessage
- 功能:一个特殊的消息基类,可被继承。所有继承自
ToRendererMessage的Message将被发往渲染进程 - 逻辑:该消息类型需要两个特殊标记,
__virid_target标记了目的地,__virid_message_type标记了在目的地应该被还原为的Message类型 - 示例:
//在主进程
import { ToRendererMessage } from "@virid/main";
// __virid_target=‘renderer’,说明消息需要发往windowId为renderer的渲染进程
// __virid_message_type: string = 'file-dialog',描述了在渲染进程,该消息将会重新变为的类型
export class RenderDialogMessage extends ToRendererMessage {
__virid_target: string = "renderer";
__virid_message_type: string = "file-dialog";
constructor(public path: string) {
super();
}
}在渲染进程,可以通过@FromIpc结合FromMainMessage来实现对应的转换。详情见@virid/renderer 。
//在渲染进程
import { FromIpc, FromMainMessage } from "@virid/main";
//@FromIpc('file-dialog')表明当主进程发送一个ToRenderMessage,而且
// __virid_target: string = 'renderer'
// __virid_message_type: string = 'file-dialog'
// 时,这个消息将被自动投递到virid调度中心触发相应的渲染进程System
@FromIpc("file-dialog")
class ChooseBgImageMessage extends FromMainMessage {
constructor(public path: string) {
super();
}
}FromRenderMessage/@FromRenderer()
- 功能:一个特殊的消息基类,可被继承。所有继承自
FromRenderMessage的Message将在渲染进程发送消息时自动转换并投递到主进程的virid调度中心 - 逻辑:
@FromRenderer()接受一个字符串类型的ID,该ID与渲染进程中发送的ToMainMessage的ID应该相同。 - 示例:
//在主进程
import { FromRenderer, FromRenderMessage } from "@virid/renderer";
// 发往渲染进程的消息
export class RenderDialogMessage extends ToRendererMessage {
__virid_target: string = "renderer";
__virid_message_type: string = "file-dialog";
constructor(public path: string) {
super();
}
}
// 将来自渲染进程且 __virid_message_type: string = 'file-dialog'的消息转换成主进程的OpenDialogMessage
@FromRenderer("open-dialog")
export class OpenDialogMessage extends FromRenderMessage {
constructor(
public options: {
title?: string;
filters?: Array<{ name: string; extensions: string[] }>;
properties?: Array<
"openFile" | "openDirectory" | "multiSelections" | "showHiddenFiles"
>;
},
) {
super();
}
}
export class WindowSystem {
@System()
async openDialog(@Message(OpenDialogMessage) message: OpenDialogMessage) {
// 调用原生对话框
const result = await dialog.showOpenDialog(
message.senderWindow,
message.options,
);
// 如果用户没有取消,并且确实选择了文件
if (!result.canceled && result.filePaths.length > 0) {
const selectedPath = result.filePaths[0];
return new RenderDialogMessage(selectedPath);
}
return;
}
}在渲染进程,可以通过@FromIpc结合ToMainMessage来实现对应的转换和消息的发送。详情见@virid/renderer 。
// 在渲染进程
import { ToMainMessage,FromIpc } from '@virid/renderer'
// 打开文件选择框
@FromIpc('file-dialog')
class ChooseBgImageMessage extends FromMainMessage {
constructor(public path: string) {
super()
}
}
//打开文件选择框
class OpenDialogMessage extends ToMainMessage {
__virid_target: string = 'main'
__virid_message_type: string = 'open-dialog'
constructor(
public options: {
title?: string
filters?: Array<{ name: string; extensions: string[] }>
properties?: Array<'openFile' | 'openDirectory' | 'multiSelections' | 'showHiddenFiles'>
}
) {
super()
}
}
