nexfep 0.0.4 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README-CN.md CHANGED
@@ -112,6 +112,49 @@ pool.onCustomMessage = (window, data) => {
112
112
  - `window` — 发送消息的窗口对象
113
113
  - `data` — 消息内容,为对象类型(JSON 序列化后会自动通过 `JSON.parse` 转换为对象)
114
114
 
115
+ #### 触发自定义事件
116
+
117
+ 在页面中通过 `window.invoke` 触发事件:
118
+
119
+ ```javascript
120
+ window.invoke('hello', 'world');
121
+ ```
122
+
123
+ **参数说明**
124
+
125
+ - `event` — 事件名称
126
+ - `data` — 任意类型的可序列化数据,会被序列化为 JSON 字符串后发送
127
+
128
+ #### 监听事件
129
+
130
+ 在主进程中通过 `pool.handle` 监听事件:
131
+
132
+ ```typescript
133
+ pool.handle('hello', (data) => {
134
+ console.log('收到事件 hello:', data);
135
+ });
136
+ ```
137
+
138
+ **参数说明**
139
+
140
+ - `event` — 事件名称,需要和触发事件时的事件名称一致
141
+ - `callback` — 事件处理函数,需要接收事件数据作为 `data` 参数。返回任意类型的可序列化数据,会被序列化为 JSON 字符串后发送至前端作为 `window.invoke` 的返回值(也可以不返回任何值)
142
+
143
+ #### 取消监听事件
144
+
145
+ 在主进程中通过 `pool.unhandle` 取消监听事件:
146
+
147
+ ```typescript
148
+ pool.unhandle('hello', (data) => {
149
+ console.log('收到事件 hello:', data);
150
+ });
151
+ ```
152
+
153
+ **参数说明**
154
+
155
+ - `event` — 事件名称,需要和触发事件时的事件名称一致
156
+ - `callback` — 事件处理函数,需要和监听事件时的回调函数一致
157
+
115
158
  #### 窗口控制函数
116
159
 
117
160
  页面中可直接调用以下注入函数进行窗口控制:
@@ -203,6 +246,8 @@ if (window.isNexfepLoadDone) {
203
246
  | ------------------------------------- | ----------------------------------------------------------- | ---------------- | -------------------------- |
204
247
  | `constructor(userDataFolder?)` | `userDataFolder`: string(可选) | WindowPool | 创建窗口池,可选指定 WebView2 用户数据目录 |
205
248
  | `createWindow(isShow?, isDecorated?)` | `isShow`: boolean(默认 true), `isDecorated`: boolean(默认 true) | Promise\<Window> | 创建并获取一个窗口 |
249
+ | `handle(event, callback)` | `event`: string, `callback`: (data: string) => void | 无 | 监听指定事件,当收到事件时触发回调函数 |
250
+ | `unhandle(event, callback)` | `event`: string, `callback`: (data: string) => void | 无 | 取消监听指定事件回调中的指定函数 |
206
251
  | `closeWindow(window)` | `window`: Window | Promise\<void> | 关闭指定窗口并回收至池中 |
207
252
  | `closePool()` | 无 | Promise\<void> | 关闭窗口池,退出应用 |
208
253
  | `mainloop()` | 无 | void | 启动应用主循环,阻塞直到应用退出 |
@@ -237,4 +282,4 @@ pnpm run compile
237
282
 
238
283
  ## 许可证
239
284
 
240
- MIT License
285
+ MIT License
package/README.md CHANGED
@@ -112,6 +112,49 @@ pool.onCustomMessage = (window, data) => {
112
112
  - `window` — The window object that sent the message
113
113
  - `data` — Message content, an object type (automatically converted from JSON string via `JSON.parse`)
114
114
 
115
+ #### Invoke Custom Events
116
+
117
+ Invoke events via `window.invoke` in the page:
118
+
119
+ ```javascript
120
+ window.invoke('hello', 'world');
121
+ ```
122
+
123
+ **Parameters**
124
+
125
+ - `event` — Event name
126
+ - `data` — Any serializable data, will be serialized to JSON string before sending
127
+
128
+ #### Listen for Events
129
+
130
+ Listen for events via `pool.handle` in the main process:
131
+
132
+ ```typescript
133
+ pool.handle('hello', (data) => {
134
+ console.log('Received event hello:', data);
135
+ });
136
+ ```
137
+
138
+ **Parameters**
139
+
140
+ - `event` — Event name, must match the event name when invoking
141
+ - `callback` — Event handler function, receives event data as `data` parameter. Can return any serializable data, which will be serialized to JSON string and sent back to the frontend as the return value of `window.invoke` (can also return nothing)
142
+
143
+ #### Remove Event Listener
144
+
145
+ Remove event listener via `pool.unhandle` in the main process:
146
+
147
+ ```typescript
148
+ pool.unhandle('hello', (data) => {
149
+ console.log('Received event hello:', data);
150
+ });
151
+ ```
152
+
153
+ **Parameters**
154
+
155
+ - `event` — Event name, must match the event name when listening
156
+ - `callback` — Event handler function, must match the callback function when listening
157
+
115
158
  #### Window Control Functions
116
159
 
117
160
  The following injected functions can be directly called in the page for window control:
@@ -203,6 +246,8 @@ if (window.isNexfepLoadDone) {
203
246
  | ------------------------------------- | -------------------------------------------------------------------------- | ---------------- | ------------------------------------------------------------------------ |
204
247
  | `constructor(userDataFolder?)` | `userDataFolder`: string (optional) | WindowPool | Creates a window pool, optionally specifying the WebView2 user data directory |
205
248
  | `createWindow(isShow?, isDecorated?)` | `isShow`: boolean (default true), `isDecorated`: boolean (default true) | Promise\<Window> | Creates and returns a window |
249
+ | `handle(event, callback)` | `event`: string, `callback`: (data: string) => void | None | Listens for the specified event, triggers callback when event is received |
250
+ | `unhandle(event, callback)` | `event`: string, `callback`: (data: string) => void | None | Removes the specified callback from the event listener |
206
251
  | `closeWindow(window)` | `window`: Window | Promise\<void> | Closes the specified window and returns it to the pool |
207
252
  | `closePool()` | None | Promise\<void> | Closes the window pool and exits the application |
208
253
  | `mainloop()` | None | void | Starts the application main loop, blocking until the application exits |
@@ -237,4 +282,4 @@ pnpm run compile
237
282
 
238
283
  ## License
239
284
 
240
- MIT License
285
+ MIT License
package/index.d.ts CHANGED
@@ -27,6 +27,8 @@ declare class WindowPool {
27
27
  onCustomMessage: (window: Window, data: string) => void;
28
28
  private app;
29
29
  private windows;
30
+ private handlers;
31
+ private injectCount;
30
32
  private windowCount;
31
33
  private freeWindowCount;
32
34
  constructor(WindowsWebview2UserDataFolder?: string);
@@ -36,6 +38,8 @@ declare class WindowPool {
36
38
  createWindow(isShow?: boolean, isDecorated?: boolean): Promise<Window>;
37
39
  closeWindow(window: Window): Promise<void>;
38
40
  closePool(): Promise<void>;
41
+ handle(event: string, callback: (data: any) => any): Promise<void>;
42
+ unhandle(event: string, callback: (data: any) => any): Promise<void>;
39
43
  mainloop(): void;
40
44
  }
41
- export { WindowPool, Window };
45
+ export { WindowPool, Window };
package/index.js CHANGED
@@ -73,6 +73,8 @@ class WindowPool {
73
73
  onCustomMessage;
74
74
  app;
75
75
  windows;
76
+ handlers;
77
+ injectCount;
76
78
  windowCount;
77
79
  freeWindowCount;
78
80
  constructor(WindowsWebview2UserDataFolder = path.join(process.env.LOCALAPPDATA || os.homedir(), 'NexfepDevelopment.webview2-data')) {
@@ -88,7 +90,9 @@ class WindowPool {
88
90
  this.onCustomMessage = (window, data) => {
89
91
  console.log('Get Custom Message:', data, "from window", window.id);
90
92
  };
93
+ this.handlers = new Map();
91
94
  this.app = new Application();
95
+ this.injectCount = 0;
92
96
  this.windows = [];
93
97
  this.windowCount = 0;
94
98
  this.freeWindowCount = 0;
@@ -182,6 +186,23 @@ class WindowPool {
182
186
  const MessageBody = { type: 'CustomMessage', data: data }
183
187
  window.ipc.postMessage(JSON.stringify(MessageBody));
184
188
  };
189
+
190
+ window.eventCount = 0;
191
+
192
+ window.invoke = async (event, data) => {
193
+ const MessageBody = { type: 'NexfepInvoke', eventId: [${this.injectCount}, ++window.eventCount], event: event, data: data }
194
+ window.ipc.postMessage(JSON.stringify(MessageBody));
195
+ return new Promise((resolve, reject) => {
196
+ window.addEventListener("nexfep-invoke-result-"+${this.injectCount}+"-"+window.eventCount, (event) => {
197
+ window.removeEventListener("nexfep-invoke-result-"+${this.injectCount}+"-"+window.eventCount, event);
198
+ if(event.detail){
199
+ resolve(event.detail);
200
+ }else{
201
+ resolve();
202
+ }
203
+ });
204
+ });
205
+ }
185
206
 
186
207
  // 注入 CSS 样式
187
208
  const style = document.createElement('style');
@@ -247,6 +268,22 @@ class WindowPool {
247
268
  else if (dataObj.type == 'CustomMessage') {
248
269
  this.onCustomMessage(windowObj, dataObj.data);
249
270
  }
271
+ else if (dataObj.type == 'NexfepInvoke') {
272
+ const handlers = this.handlers.get(dataObj.event) || [];
273
+ handlers.forEach(async (handler) => {
274
+ const result = await handler(dataObj.data);
275
+ if (result) {
276
+ webview.evaluateScript(`
277
+ window.dispatchEvent(new Event('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: ${JSON.stringify(result)} }));
278
+ `);
279
+ }
280
+ else {
281
+ webview.evaluateScript(`
282
+ window.dispatchEvent(new Event('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: undefined }));
283
+ `);
284
+ }
285
+ });
286
+ }
250
287
  });
251
288
  return windowObj;
252
289
  }
@@ -282,9 +319,14 @@ class WindowPool {
282
319
  async closePool() {
283
320
  this.app.exit();
284
321
  }
322
+ async handle(event, callback) {
323
+ this.handlers.set(event, [...this.handlers.get(event) || [], callback]);
324
+ }
325
+ async unhandle(event, callback) {
326
+ this.handlers.set(event, (this.handlers.get(event) || []).filter(c => c !== callback));
327
+ }
285
328
  mainloop() {
286
329
  this.app.run();
287
330
  }
288
331
  }
289
332
  export { WindowPool, Window };
290
- //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "webview",
15
15
  "typescript"
16
16
  ],
17
- "version": "0.0.4",
17
+ "version": "0.1.0",
18
18
  "type": "module",
19
19
  "packageManager": "pnpm@9.15.9",
20
20
  "main": "./index.js",