nexfep 0.6.0 → 0.6.1
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 +22 -3
- package/README.md +21 -2
- package/package.json +2 -2
- package/src/SingleInstance.d.ts +2 -2
- package/src/SingleInstance.js +2 -2
- package/src/WindowManager.d.ts +2 -0
- package/src/WindowManager.js +23 -22
package/README-CN.md
CHANGED
|
@@ -148,15 +148,22 @@ const locker = app.createLocker("my-app");
|
|
|
148
148
|
try {
|
|
149
149
|
// 尝试获取应用实例锁
|
|
150
150
|
await locker.lock();
|
|
151
|
+
// 也可以带参数获取锁,例如:
|
|
152
|
+
// await locker.lock(process.argv[2]);
|
|
151
153
|
} catch {
|
|
152
154
|
// 应用实例已存在,退出应用
|
|
153
155
|
app.exit();
|
|
154
156
|
}
|
|
155
|
-
//
|
|
156
|
-
locker.whenLost(() => {
|
|
157
|
+
// 你可以在其它实例抢锁时聚焦当前实例
|
|
158
|
+
locker.whenLost((data) => {
|
|
157
159
|
if (!win.isFocused()) {
|
|
158
160
|
win.focus();
|
|
159
161
|
}
|
|
162
|
+
// 如果对方实例在获取锁时传递了参数,你可以使用它来执行特定操作
|
|
163
|
+
// 若没有传递,data 字段将会是 null
|
|
164
|
+
if (data) {
|
|
165
|
+
console.log("传递了参数:", data);
|
|
166
|
+
}
|
|
160
167
|
});
|
|
161
168
|
// 释放锁
|
|
162
169
|
locker.unlock();
|
|
@@ -166,7 +173,7 @@ locker.unlock();
|
|
|
166
173
|
|
|
167
174
|
| 方法 | 描述 |
|
|
168
175
|
| -------------------- | ------------------------ |
|
|
169
|
-
| `lock()`
|
|
176
|
+
| `lock(data?)` | 尝试获取应用实例锁 |
|
|
170
177
|
| `whenLost(callback)` | 当其它实例抢锁时执行回调 |
|
|
171
178
|
| `unlock()` | 释放锁 |
|
|
172
179
|
|
|
@@ -404,6 +411,12 @@ window.addEventListener("user-login", (event) => {
|
|
|
404
411
|
});
|
|
405
412
|
```
|
|
406
413
|
|
|
414
|
+
特别地,主进程可以通过 `pool.broadcast` 向所有打开的窗口发送事件,参数与页面中的 `window.broadcast` 相同:
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
pool.broadcast("user-login", { userId: 123 });
|
|
418
|
+
```
|
|
419
|
+
|
|
407
420
|
#### 定向发送
|
|
408
421
|
|
|
409
422
|
通过 `window.tell` 向指定 ID 的窗口发送消息:
|
|
@@ -432,6 +445,12 @@ window.addEventListener("custom-message", (event) => {
|
|
|
432
445
|
console.log("当前窗口 ID:", window.id);
|
|
433
446
|
```
|
|
434
447
|
|
|
448
|
+
主进程也可通过 `win.tell` 向该窗口发送消息:
|
|
449
|
+
|
|
450
|
+
```typescript
|
|
451
|
+
win.tell("custom-message", { text: `你好,窗口 ${win.id}` });
|
|
452
|
+
```
|
|
453
|
+
|
|
435
454
|
### 自定义消息
|
|
436
455
|
|
|
437
456
|
#### 发送消息
|
package/README.md
CHANGED
|
@@ -148,15 +148,22 @@ const locker = app.createLocker("my-app");
|
|
|
148
148
|
try {
|
|
149
149
|
// Try to acquire the lock
|
|
150
150
|
await locker.lock();
|
|
151
|
+
// You can also pass data to the other instance when acquiring the lock
|
|
152
|
+
// await locker.lock(process.argv[2]);
|
|
151
153
|
} catch {
|
|
152
154
|
// Instance already exists, exit the application
|
|
153
155
|
app.exit();
|
|
154
156
|
}
|
|
155
157
|
// Focus the current instance when other instances acquire the lock
|
|
156
|
-
locker.whenLost(() => {
|
|
158
|
+
locker.whenLost((data) => {
|
|
157
159
|
if (!win.isFocused()) {
|
|
158
160
|
win.focus();
|
|
159
161
|
}
|
|
162
|
+
// If the other instance passed data, you can use it to perform specific actions
|
|
163
|
+
// If no data was passed, data will be null
|
|
164
|
+
if (data) {
|
|
165
|
+
console.log("Other instance passed data:", data);
|
|
166
|
+
}
|
|
160
167
|
});
|
|
161
168
|
// Release the lock
|
|
162
169
|
locker.unlock();
|
|
@@ -164,7 +171,7 @@ locker.unlock();
|
|
|
164
171
|
|
|
165
172
|
**Methods**
|
|
166
173
|
|
|
167
|
-
- `lock()` — Try to acquire the lock
|
|
174
|
+
- `lock(data?)` — Try to acquire the lock
|
|
168
175
|
- `whenLost(callback)` — Register a callback to be called when other instances acquire the lock
|
|
169
176
|
- `unlock()` — Release the lock
|
|
170
177
|
|
|
@@ -402,6 +409,12 @@ window.addEventListener("user-login", (event) => {
|
|
|
402
409
|
});
|
|
403
410
|
```
|
|
404
411
|
|
|
412
|
+
The main process can send events to all open windows via `pool.broadcast`, with parameters identical to those of `window.broadcast` in the page:
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
pool.broadcast("user-login", { userId: 123 });
|
|
416
|
+
```
|
|
417
|
+
|
|
405
418
|
#### Tell
|
|
406
419
|
|
|
407
420
|
Send a message to a specific window by its ID via `window.tell`:
|
|
@@ -430,6 +443,12 @@ Each window's ID can be accessed via `window.id`:
|
|
|
430
443
|
console.log("This window ID:", window.id);
|
|
431
444
|
```
|
|
432
445
|
|
|
446
|
+
The main process can also send messages to this window through `win.tell`:
|
|
447
|
+
|
|
448
|
+
```typescript
|
|
449
|
+
win.tell("custom-message", { text: `Hello Window ${win.id}` });
|
|
450
|
+
```
|
|
451
|
+
|
|
433
452
|
### Custom Messages
|
|
434
453
|
|
|
435
454
|
#### Send Messages
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexfep",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "A desktop application framework based on @webviewjs/webview",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"@webviewjs/webview",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"lint:fix": "oxlint --fix"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@nexfteam/single-instance": "
|
|
68
|
+
"@nexfteam/single-instance": "0.0.8",
|
|
69
69
|
"@webviewjs/webview": "0.4.1"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
package/src/SingleInstance.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { SingleInstance } from "@nexfteam/single-instance";
|
|
|
2
2
|
declare class Locker {
|
|
3
3
|
locker: SingleInstance;
|
|
4
4
|
constructor(appName: string);
|
|
5
|
-
lock(): Promise<void>;
|
|
5
|
+
lock(data?: string): Promise<void>;
|
|
6
6
|
unlock(): Promise<void>;
|
|
7
|
-
whenLost(callback: () => void): void;
|
|
7
|
+
whenLost(callback: (data?: string) => void): void;
|
|
8
8
|
}
|
|
9
9
|
export { Locker };
|
package/src/SingleInstance.js
CHANGED
package/src/WindowManager.d.ts
CHANGED
|
@@ -34,6 +34,7 @@ declare class Window {
|
|
|
34
34
|
getPosition(): import("@webviewjs/webview").Position;
|
|
35
35
|
isFocused(): boolean;
|
|
36
36
|
focus(): void;
|
|
37
|
+
tell(message: string, data: any): void;
|
|
37
38
|
hide(): void;
|
|
38
39
|
show(): void;
|
|
39
40
|
close(): void;
|
|
@@ -69,5 +70,6 @@ declare class WindowPool {
|
|
|
69
70
|
closeWindow(window: Window): Promise<void>;
|
|
70
71
|
handle(event: string, callback: (data: any) => any): Promise<void>;
|
|
71
72
|
unhandle(event: string, callback: (data: any) => any): Promise<void>;
|
|
73
|
+
broadcast(event: string, data: any): Promise<void>;
|
|
72
74
|
}
|
|
73
75
|
export { WindowPool, Window };
|
package/src/WindowManager.js
CHANGED
|
@@ -121,6 +121,9 @@ class Window {
|
|
|
121
121
|
this.unMinimize();
|
|
122
122
|
this.window.focus();
|
|
123
123
|
}
|
|
124
|
+
tell(message, data) {
|
|
125
|
+
this.webview.evaluateScript(`window.dispatchEvent(new CustomEvent('${message}', { detail: ${JSON.stringify(data)} }));`);
|
|
126
|
+
}
|
|
124
127
|
hide() {
|
|
125
128
|
this.window.hide();
|
|
126
129
|
this.isShow = false;
|
|
@@ -370,13 +373,14 @@ class WindowPool {
|
|
|
370
373
|
const dataText = data.body.toString();
|
|
371
374
|
const dataObj = JSON.parse(dataText);
|
|
372
375
|
if (dataObj.type == "NexfepBeforeUnload") {
|
|
373
|
-
webview.evaluateScript(`
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
376
|
+
webview.evaluateScript(`
|
|
377
|
+
if(window?.isNexfepLoadDone){
|
|
378
|
+
const MessageBody = { type: 'NexfepBeforeUnload' }
|
|
379
|
+
window.ipc.postMessage(JSON.stringify(MessageBody));
|
|
380
|
+
}else{
|
|
381
|
+
const MessageBody = { type: 'NexfepLoadFalse' }
|
|
382
|
+
window.ipc.postMessage(JSON.stringify(MessageBody));
|
|
383
|
+
}`);
|
|
380
384
|
}
|
|
381
385
|
else if (dataObj.type == "NexfepLoadFalse") {
|
|
382
386
|
this.__injectControlFunctions(windowObj);
|
|
@@ -416,14 +420,10 @@ class WindowPool {
|
|
|
416
420
|
handlers.forEach(async (handler) => {
|
|
417
421
|
const result = await handler(dataObj.data);
|
|
418
422
|
if (result) {
|
|
419
|
-
webview.evaluateScript(`
|
|
420
|
-
window.dispatchEvent(new CustomEvent('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: ${JSON.stringify(result)} }));
|
|
421
|
-
`);
|
|
423
|
+
webview.evaluateScript(`window.dispatchEvent(new CustomEvent('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: ${JSON.stringify(result)} }));`);
|
|
422
424
|
}
|
|
423
425
|
else {
|
|
424
|
-
webview.evaluateScript(`
|
|
425
|
-
window.dispatchEvent(new CustomEvent('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: undefined }));
|
|
426
|
-
`);
|
|
426
|
+
webview.evaluateScript(`window.dispatchEvent(new CustomEvent('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: undefined }));`);
|
|
427
427
|
}
|
|
428
428
|
});
|
|
429
429
|
}
|
|
@@ -432,16 +432,12 @@ class WindowPool {
|
|
|
432
432
|
}
|
|
433
433
|
else if (dataObj.type == "NexfepGetGlobal") {
|
|
434
434
|
const value = this.global.get(dataObj.name);
|
|
435
|
-
webview.evaluateScript(`
|
|
436
|
-
window.dispatchEvent(new CustomEvent('nexfep-get-global-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: ${JSON.stringify(value)} }));
|
|
437
|
-
`);
|
|
435
|
+
webview.evaluateScript(`window.dispatchEvent(new CustomEvent('nexfep-get-global-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: ${JSON.stringify(value)} }));`);
|
|
438
436
|
}
|
|
439
437
|
else if (dataObj.type == "NexfepBroadcast") {
|
|
440
438
|
this.windows.forEach(async (w) => {
|
|
441
439
|
if (w != windowObj && w.isOpen) {
|
|
442
|
-
w.webview.evaluateScript(`
|
|
443
|
-
window.dispatchEvent(new CustomEvent('${dataObj.name}', { detail: ${JSON.stringify(dataObj.data)} }));
|
|
444
|
-
`);
|
|
440
|
+
w.webview.evaluateScript(`window.dispatchEvent(new CustomEvent('${dataObj.name}', { detail: ${JSON.stringify(dataObj.data)} }));`);
|
|
445
441
|
}
|
|
446
442
|
});
|
|
447
443
|
}
|
|
@@ -451,9 +447,7 @@ class WindowPool {
|
|
|
451
447
|
}
|
|
452
448
|
this.windows.forEach(async (w) => {
|
|
453
449
|
if (w.id == dataObj.to) {
|
|
454
|
-
w.webview.evaluateScript(`
|
|
455
|
-
window.dispatchEvent(new CustomEvent('${dataObj.message}', { detail: ${JSON.stringify(dataObj.data)} }));
|
|
456
|
-
`);
|
|
450
|
+
w.webview.evaluateScript(`window.dispatchEvent(new CustomEvent('${dataObj.message}', { detail: ${JSON.stringify(dataObj.data)} }));`);
|
|
457
451
|
}
|
|
458
452
|
});
|
|
459
453
|
}
|
|
@@ -518,5 +512,12 @@ class WindowPool {
|
|
|
518
512
|
async unhandle(event, callback) {
|
|
519
513
|
this.handlers.set(event, (this.handlers.get(event) || []).filter((c) => c !== callback));
|
|
520
514
|
}
|
|
515
|
+
async broadcast(event, data) {
|
|
516
|
+
this.windows.forEach(async (w) => {
|
|
517
|
+
if (w.isOpen) {
|
|
518
|
+
w.webview.evaluateScript(`window.dispatchEvent(new CustomEvent('${event}', { detail: ${JSON.stringify(data)} }));`);
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
}
|
|
521
522
|
}
|
|
522
523
|
export { WindowPool, Window };
|