nexfep 0.0.3 → 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 +47 -2
- package/README.md +47 -2
- package/index.d.ts +5 -1
- package/index.js +43 -1
- package/package.json +14 -1
package/README-CN.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Nexfep
|
|
2
2
|
|
|
3
|
-
语言: [English](https://github.com/zhuxiaojt/Nexfep/blob/
|
|
3
|
+
语言: [English](https://github.com/zhuxiaojt/Nexfep/blob/main/README.md) | 简体中文(当前)
|
|
4
4
|
|
|
5
5
|
基于 @webviewjs/webview 的桌面应用框架
|
|
6
6
|
|
|
@@ -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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Nexfep
|
|
2
2
|
|
|
3
|
-
Language: English(now) | [简体中文](https://github.com/zhuxiaojt/Nexfep/blob/
|
|
3
|
+
Language: English(now) | [简体中文](https://github.com/zhuxiaojt/Nexfep/blob/main/README-CN.md)
|
|
4
4
|
|
|
5
5
|
A desktop application framework based on @webviewjs/webview
|
|
6
6
|
|
|
@@ -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
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexfep",
|
|
3
3
|
"description": "A desktop application framework based on @webviewjs/webview",
|
|
4
|
-
"
|
|
4
|
+
"repository": "https://github.com/zhuxiaojt/Nexfep",
|
|
5
|
+
"homepage": "https://github.com/zhuxiaojt/Nexfep#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/zhuxiaojt/Nexfep/issues"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"desktop",
|
|
11
|
+
"application",
|
|
12
|
+
"framework",
|
|
13
|
+
"@webviewjs/webview",
|
|
14
|
+
"webview",
|
|
15
|
+
"typescript"
|
|
16
|
+
],
|
|
17
|
+
"version": "0.1.0",
|
|
5
18
|
"type": "module",
|
|
6
19
|
"packageManager": "pnpm@9.15.9",
|
|
7
20
|
"main": "./index.js",
|