nexfep 0.1.3 → 0.1.5

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
@@ -117,13 +117,14 @@ pool.onCustomMessage = (window, data) => {
117
117
  在页面中通过 `window.invoke` 触发事件:
118
118
 
119
119
  ```javascript
120
+ window.invoke('hello');
120
121
  window.invoke('hello', 'world');
121
122
  ```
122
123
 
123
124
  **参数说明**
124
125
 
125
126
  - `event` — 事件名称
126
- - `data` 任意类型的可序列化数据,会被序列化为 JSON 字符串后发送
127
+ - `data`(可选)— 任意类型的可序列化数据,会被序列化为 JSON 字符串后发送
127
128
 
128
129
  #### 监听事件
129
130
 
@@ -192,6 +193,59 @@ globals.set('hello', 'world');
192
193
  const value = globals.get('hello');
193
194
  ```
194
195
 
196
+ ### 窗口间通信
197
+
198
+ 框架支持窗口之间通过 `window.broadcast` 和 `window.tell` 直接通信,无需经过主进程。
199
+
200
+ #### 广播
201
+
202
+ 通过 `window.broadcast` 向所有其他打开的窗口发送事件:
203
+
204
+ ```javascript
205
+ window.broadcast('user-login', { userId: 123 });
206
+ ```
207
+
208
+ **参数说明**
209
+
210
+ - `name` — 事件名称
211
+ - `data`(可选)— 任意类型的可序列化数据,会被序列化为 JSON 字符串后发送
212
+
213
+ 其他窗口通过 `window.addEventListener` 监听广播事件:
214
+
215
+ ```javascript
216
+ window.addEventListener('user-login', (event) => {
217
+ console.log('用户已登录:', event.detail);
218
+ });
219
+ ```
220
+
221
+ #### 定向发送
222
+
223
+ 通过 `window.tell` 向指定 ID 的窗口发送消息:
224
+
225
+ ```javascript
226
+ window.tell(2, 'custom-message', { text: '你好,窗口2' });
227
+ ```
228
+
229
+ **参数说明**
230
+
231
+ - `to` — 目标窗口 ID(数字类型)
232
+ - `message` — 事件名称
233
+ - `data`(可选)— 任意类型的可序列化数据,会被序列化为 JSON 字符串后发送
234
+
235
+ 目标窗口通过 `window.addEventListener` 接收消息:
236
+
237
+ ```javascript
238
+ window.addEventListener('custom-message', (event) => {
239
+ console.log('收到消息:', event.detail);
240
+ });
241
+ ```
242
+
243
+ 每个窗口的 ID 可通过 `window.id` 获取:
244
+
245
+ ```javascript
246
+ console.log('当前窗口 ID:', window.id);
247
+ ```
248
+
195
249
  ### 窗口控制函数
196
250
 
197
251
  页面中可直接调用以下注入函数进行窗口控制:
@@ -207,6 +261,13 @@ window.openDevTools(); // 打开开发者工具
207
261
  window.closeDevTools(); // 关闭开发者工具
208
262
  ```
209
263
 
264
+ 页面中还可访问以下属性:
265
+
266
+ ```javascript
267
+ console.log(window.id); // 窗口唯一标识
268
+ console.log(window.isNexfepLoadDone); // 窗口是否已加载完成
269
+ ```
270
+
210
271
  ### 拖拽区域
211
272
 
212
273
  通过 HTML 属性即可定义窗口拖拽区域,无需编写额外 JavaScript 代码。这些属性会自动应用 `-webkit-app-region` 和 `app-region` CSS 属性。
package/README.md CHANGED
@@ -117,13 +117,14 @@ pool.onCustomMessage = (window, data) => {
117
117
  Invoke events via `window.invoke` in the page:
118
118
 
119
119
  ```javascript
120
+ window.invoke('hello');
120
121
  window.invoke('hello', 'world');
121
122
  ```
122
123
 
123
124
  **Parameters**
124
125
 
125
126
  - `event` — Event name
126
- - `data` — Any serializable data, will be serialized to JSON string before sending
127
+ - `data` (optional) — Any serializable data, will be serialized to JSON string before sending
127
128
 
128
129
  #### Listen for Events
129
130
 
@@ -192,6 +193,59 @@ globals.set('hello', 'world');
192
193
  const value = globals.get('hello');
193
194
  ```
194
195
 
196
+ ### Inter-Window Communication
197
+
198
+ The framework supports direct communication between windows via `window.broadcast` and `window.tell`, without going through the main process.
199
+
200
+ #### Broadcast
201
+
202
+ Send an event to all other open windows via `window.broadcast`:
203
+
204
+ ```javascript
205
+ window.broadcast('user-login', { userId: 123 });
206
+ ```
207
+
208
+ **Parameters**
209
+
210
+ - `name` — Event name
211
+ - `data` (optional) — Any serializable data, will be serialized to JSON string before sending
212
+
213
+ Other windows listen for the broadcast event via `window.addEventListener`:
214
+
215
+ ```javascript
216
+ window.addEventListener('user-login', (event) => {
217
+ console.log('User logged in:', event.detail);
218
+ });
219
+ ```
220
+
221
+ #### Tell
222
+
223
+ Send a message to a specific window by its ID via `window.tell`:
224
+
225
+ ```javascript
226
+ window.tell(2, 'custom-message', { text: 'Hello Window 2' });
227
+ ```
228
+
229
+ **Parameters**
230
+
231
+ - `to` — Target window ID (number)
232
+ - `message` — Event name
233
+ - `data` (optional) — Any serializable data, will be serialized to JSON string before sending
234
+
235
+ The target window receives the message via `window.addEventListener`:
236
+
237
+ ```javascript
238
+ window.addEventListener('custom-message', (event) => {
239
+ console.log('Received message:', event.detail);
240
+ });
241
+ ```
242
+
243
+ Each window's ID can be accessed via `window.id`:
244
+
245
+ ```javascript
246
+ console.log('This window ID:', window.id);
247
+ ```
248
+
195
249
  ### Window Control Functions
196
250
 
197
251
  The following injected functions can be directly called in the page for window control:
@@ -207,6 +261,13 @@ window.openDevTools(); // Open developer tools
207
261
  window.closeDevTools(); // Close developer tools
208
262
  ```
209
263
 
264
+ The following properties are also available in the page:
265
+
266
+ ```javascript
267
+ console.log(window.id); // Window unique identifier
268
+ console.log(window.isNexfepLoadDone); // Whether the window has finished loading
269
+ ```
270
+
210
271
  ### Drag Regions
211
272
 
212
273
  Define window drag regions via HTML attributes without writing additional JavaScript code. These attributes automatically apply `-webkit-app-region` and `app-region` CSS properties.
package/index.js CHANGED
@@ -187,7 +187,7 @@ class WindowPool {
187
187
 
188
188
  window.eventCount = 0;
189
189
 
190
- window.invoke = async (event, data) => {
190
+ window.invoke = async (event, data = null) => {
191
191
  const MessageBody = { type: 'NexfepInvoke', eventId: [${this.injectCount}, ++window.eventCount], event: event, data: data }
192
192
  window.ipc.postMessage(JSON.stringify(MessageBody));
193
193
  return new Promise((resolve, reject) => {
@@ -221,6 +221,18 @@ class WindowPool {
221
221
  });
222
222
  });
223
223
  }
224
+
225
+ window.broadcast = (name, data = null) => {
226
+ const MessageBody = { type: 'NexfepBroadcast', name: name, data: data }
227
+ window.ipc.postMessage(JSON.stringify(MessageBody));
228
+ }
229
+
230
+ window.id = ${windowObj.id};
231
+
232
+ window.tell = (to, message, data = null) => {
233
+ const MessageBody = { type: 'NexfepTell', to: to, message: message, data: data }
234
+ window.ipc.postMessage(JSON.stringify(MessageBody));
235
+ }
224
236
 
225
237
  // 注入 CSS 样式
226
238
  const style = document.createElement('style');
@@ -231,7 +243,7 @@ class WindowPool {
231
243
  window.isNexfepLoadDone = true;
232
244
 
233
245
  // 触发加载完成事件
234
- window.dispatchEvent(new Event('nexfep-load-done'));
246
+ window.dispatchEvent(new CustomEvent('nexfep-load-done'));
235
247
  `;
236
248
  await this.__injectCode(windowObj, INJECT_CODE);
237
249
  }
@@ -290,12 +302,12 @@ class WindowPool {
290
302
  const result = await handler(dataObj.data);
291
303
  if (result) {
292
304
  webview.evaluateScript(`
293
- window.dispatchEvent(new Event('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: ${JSON.stringify(result)} }));
305
+ window.dispatchEvent(new CustomEvent('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: ${JSON.stringify(result)} }));
294
306
  `);
295
307
  }
296
308
  else {
297
309
  webview.evaluateScript(`
298
- window.dispatchEvent(new Event('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: undefined }));
310
+ window.dispatchEvent(new CustomEvent('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: undefined }));
299
311
  `);
300
312
  }
301
313
  });
@@ -306,9 +318,27 @@ class WindowPool {
306
318
  else if (dataObj.type == 'NexfepGetGlobal') {
307
319
  const value = this.global.get(dataObj.name);
308
320
  webview.evaluateScript(`
309
- window.dispatchEvent(new Event('nexfep-get-global-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: ${JSON.stringify(value)} }));
321
+ window.dispatchEvent(new CustomEvent('nexfep-get-global-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: ${JSON.stringify(value)} }));
310
322
  `);
311
323
  }
324
+ else if (dataObj.type == 'NexfepBroadcast') {
325
+ this.windows.forEach(async (w) => {
326
+ if (w != windowObj && w.isOpen) {
327
+ w.webview.evaluateScript(`
328
+ window.dispatchEvent(new CustomEvent('${dataObj.name}', { detail: ${JSON.stringify(dataObj.data)} }));
329
+ `);
330
+ }
331
+ });
332
+ }
333
+ else if (dataObj.type == 'NexfepTell') {
334
+ this.windows.forEach(async (w) => {
335
+ if (w.id == dataObj.to) {
336
+ w.webview.evaluateScript(`
337
+ window.dispatchEvent(new CustomEvent('${dataObj.message}', { detail: ${JSON.stringify(dataObj.data)} }));
338
+ `);
339
+ }
340
+ });
341
+ }
312
342
  });
313
343
  return windowObj;
314
344
  }
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "webview",
15
15
  "typescript"
16
16
  ],
17
- "version": "0.1.3",
17
+ "version": "0.1.5",
18
18
  "type": "module",
19
19
  "main": "./index.js",
20
20
  "scripts": {
@@ -25,8 +25,16 @@
25
25
  "engines": {
26
26
  "node": ">=20.11.0"
27
27
  },
28
+ "files": [
29
+ "index.js",
30
+ "index.d.ts",
31
+ "README.md",
32
+ "README-CN.md",
33
+ "LICENSE",
34
+ "package.json"
35
+ ],
28
36
  "dependencies": {
29
- "@webviewjs/webview": "^0.1.0"
37
+ "@webviewjs/webview": "0.1.4"
30
38
  },
31
39
  "devDependencies": {
32
40
  "@types/node": "^22.0.0",