nexfep 0.5.5 → 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 +144 -78
- package/README.md +143 -77
- package/frontend/index.d.ts +19 -19
- package/package.json +14 -8
- package/src/Application.d.ts +7 -4
- package/src/Application.js +4 -3
- package/src/Icon.d.ts +19 -0
- package/src/Icon.js +36 -0
- package/src/Logger.d.ts +1 -0
- package/src/Logger.js +5 -14
- package/src/SingleInstance.d.ts +2 -2
- package/src/SingleInstance.js +2 -2
- package/src/Tray.d.ts +4 -3
- package/src/Tray.js +3 -3
- package/src/WindowManager.d.ts +18 -2
- package/src/WindowManager.js +68 -28
package/src/Logger.js
CHANGED
|
@@ -16,7 +16,6 @@ class Logger {
|
|
|
16
16
|
let styleArgIndex = 1;
|
|
17
17
|
let result = "";
|
|
18
18
|
let currentAnsiStyle = "";
|
|
19
|
-
// 命名前景色映射
|
|
20
19
|
const fgColors = {
|
|
21
20
|
black: "\x1b[30m",
|
|
22
21
|
red: "\x1b[31m",
|
|
@@ -36,7 +35,6 @@ class Logger {
|
|
|
36
35
|
lightcyan: "\x1b[96m",
|
|
37
36
|
lightwhite: "\x1b[97m",
|
|
38
37
|
};
|
|
39
|
-
// 命名背景色映射
|
|
40
38
|
const bgColors = {
|
|
41
39
|
black: "\x1b[40m",
|
|
42
40
|
red: "\x1b[41m",
|
|
@@ -47,7 +45,6 @@ class Logger {
|
|
|
47
45
|
cyan: "\x1b[46m",
|
|
48
46
|
white: "\x1b[47m",
|
|
49
47
|
};
|
|
50
|
-
// 文字样式:加粗、斜体、下划线
|
|
51
48
|
const textStyles = {
|
|
52
49
|
bold: "\x1b[1m",
|
|
53
50
|
"font-weight:bold": "\x1b[1m",
|
|
@@ -57,14 +54,11 @@ class Logger {
|
|
|
57
54
|
"text-decoration:underline": "\x1b[4m",
|
|
58
55
|
none: RESET,
|
|
59
56
|
};
|
|
60
|
-
/** hex/rgb 转 ANSI 24位真彩色 */
|
|
61
57
|
function colorToAnsi(colorVal, isBg = false) {
|
|
62
58
|
let val = colorVal.trim().toLowerCase();
|
|
63
|
-
// 命名色
|
|
64
59
|
const colorMap = isBg ? bgColors : fgColors;
|
|
65
60
|
if (colorMap[val])
|
|
66
61
|
return colorMap[val];
|
|
67
|
-
// hex #fff #ffffff
|
|
68
62
|
const hexReg = /^#([0-9a-f]{3}|[0-9a-f]{6})$/;
|
|
69
63
|
if (hexReg.test(val)) {
|
|
70
64
|
let hex = val.replace("#", "");
|
|
@@ -78,7 +72,6 @@ class Logger {
|
|
|
78
72
|
const b = parseInt(hex.slice(4, 6), 16);
|
|
79
73
|
return isBg ? `\x1b[48;2;${r};${g};${b}m` : `\x1b[38;2;${r};${g};${b}m`;
|
|
80
74
|
}
|
|
81
|
-
// rgb(r,g,b)
|
|
82
75
|
const rgbReg = /rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/;
|
|
83
76
|
const rgbMatch = val.match(rgbReg);
|
|
84
77
|
if (rgbMatch) {
|
|
@@ -87,7 +80,6 @@ class Logger {
|
|
|
87
80
|
}
|
|
88
81
|
return "";
|
|
89
82
|
}
|
|
90
|
-
/** 解析CSS样式字符串为ANSI序列 */
|
|
91
83
|
function parseColorStyle(styleStr) {
|
|
92
84
|
if (!styleStr)
|
|
93
85
|
return RESET;
|
|
@@ -100,17 +92,14 @@ class Logger {
|
|
|
100
92
|
const [prop, ...rest] = rule.split(":");
|
|
101
93
|
const propKey = prop.trim().toLowerCase();
|
|
102
94
|
const value = rest.join(":").trim().toLowerCase();
|
|
103
|
-
// 文字样式
|
|
104
95
|
if (textStyles[`${propKey}:${value}`] || textStyles[value]) {
|
|
105
96
|
ansi += textStyles[`${propKey}:${value}`] ?? textStyles[value];
|
|
106
97
|
continue;
|
|
107
98
|
}
|
|
108
|
-
// 前景色
|
|
109
99
|
if (propKey === "color") {
|
|
110
100
|
ansi += colorToAnsi(value, false);
|
|
111
101
|
continue;
|
|
112
102
|
}
|
|
113
|
-
// 背景色
|
|
114
103
|
if (propKey === "background" || propKey === "background-color") {
|
|
115
104
|
ansi += colorToAnsi(value, true);
|
|
116
105
|
continue;
|
|
@@ -120,7 +109,6 @@ class Logger {
|
|
|
120
109
|
}
|
|
121
110
|
for (const segment of parts) {
|
|
122
111
|
if (segment === "%c") {
|
|
123
|
-
// 取出下一个样式参数,参数不足则重置样式
|
|
124
112
|
const styleStr = args[styleArgIndex];
|
|
125
113
|
styleArgIndex++;
|
|
126
114
|
currentAnsiStyle = parseColorStyle(String(styleStr ?? ""));
|
|
@@ -136,10 +124,8 @@ class Logger {
|
|
|
136
124
|
}
|
|
137
125
|
}
|
|
138
126
|
}
|
|
139
|
-
// 全局末尾统一重置,防止后续日志被染色
|
|
140
127
|
if (currentAnsiStyle)
|
|
141
128
|
result += RESET;
|
|
142
|
-
// 剩余非样式参数直接拼接
|
|
143
129
|
const extraArgs = args.slice(styleArgIndex);
|
|
144
130
|
if (extraArgs.length) {
|
|
145
131
|
result += " " + extraArgs.map(String).join(" ");
|
|
@@ -192,5 +178,10 @@ class Logger {
|
|
|
192
178
|
this.__printLog(0, "Debug", [args], "\x1b[90m", "\x1b[0m");
|
|
193
179
|
}
|
|
194
180
|
}
|
|
181
|
+
clear() {
|
|
182
|
+
if (this.logFilePath) {
|
|
183
|
+
fs.writeFileSync(this.logFilePath, "");
|
|
184
|
+
}
|
|
185
|
+
}
|
|
195
186
|
}
|
|
196
187
|
export { Logger };
|
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/Tray.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Application, TrayIcon
|
|
1
|
+
import { Application, TrayIcon } from "@webviewjs/webview";
|
|
2
|
+
import { Icon } from "./Icon.js";
|
|
2
3
|
declare class Tray {
|
|
3
4
|
app: Application;
|
|
4
5
|
tray: TrayIcon;
|
|
@@ -10,7 +11,7 @@ declare class Tray {
|
|
|
10
11
|
constructor(app: Application, options: {
|
|
11
12
|
id: string;
|
|
12
13
|
tooltip: string;
|
|
13
|
-
icon
|
|
14
|
+
icon?: Icon;
|
|
14
15
|
menuItems: Array<{
|
|
15
16
|
id: string;
|
|
16
17
|
label: string;
|
|
@@ -26,7 +27,7 @@ declare class Tray {
|
|
|
26
27
|
id: string;
|
|
27
28
|
label: string;
|
|
28
29
|
}>): void;
|
|
29
|
-
setIcon(icon:
|
|
30
|
+
setIcon(icon: Icon): void;
|
|
30
31
|
on(event: string, callback: (event: any) => void): void;
|
|
31
32
|
setTooltip(tooltip: string): void;
|
|
32
33
|
hide(): void;
|
package/src/Tray.js
CHANGED
|
@@ -10,7 +10,7 @@ class Tray {
|
|
|
10
10
|
this.tray = app.createTrayIcon({
|
|
11
11
|
id: options.id,
|
|
12
12
|
tooltip: options.tooltip,
|
|
13
|
-
icon: options.icon,
|
|
13
|
+
icon: options.icon?.toTrayIconImage(),
|
|
14
14
|
menu: {
|
|
15
15
|
items: this.menuItems,
|
|
16
16
|
},
|
|
@@ -36,9 +36,9 @@ class Tray {
|
|
|
36
36
|
this.menuItems = items;
|
|
37
37
|
this.tray.setMenu({ items: this.menuItems });
|
|
38
38
|
}
|
|
39
|
-
setIcon(icon
|
|
39
|
+
setIcon(icon) {
|
|
40
40
|
this.__ErrorWhenDestroyed();
|
|
41
|
-
this.tray.setIcon(icon, width, height);
|
|
41
|
+
this.tray.setIcon(icon.data, icon.width, icon.height);
|
|
42
42
|
}
|
|
43
43
|
on(event, callback) {
|
|
44
44
|
this.__ErrorWhenDestroyed();
|
package/src/WindowManager.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Application, BrowserWindow, Webview } from "@webviewjs/webview";
|
|
2
2
|
import { Logger } from "./Logger.js";
|
|
3
|
+
import { Icon } from "./Icon.js";
|
|
3
4
|
declare class Window {
|
|
4
5
|
window: BrowserWindow;
|
|
5
6
|
webview: Webview;
|
|
@@ -9,9 +10,13 @@ declare class Window {
|
|
|
9
10
|
id: number;
|
|
10
11
|
private myPool;
|
|
11
12
|
constructor(window: BrowserWindow, webview: Webview, id: number, myPool: WindowPool);
|
|
13
|
+
setLevel(level: -1 | 0 | 1): void;
|
|
14
|
+
setFullScreen(isFullScreen: boolean, options?: {
|
|
15
|
+
borderless?: boolean;
|
|
16
|
+
}): void;
|
|
12
17
|
setDecorated(isDecorated: boolean): void;
|
|
13
18
|
setTitle(title: string): void;
|
|
14
|
-
|
|
19
|
+
setResizable(resizable: boolean): void;
|
|
15
20
|
maximize(): void;
|
|
16
21
|
minimize(): void;
|
|
17
22
|
unMaximize(): void;
|
|
@@ -22,12 +27,14 @@ declare class Window {
|
|
|
22
27
|
toggleMinimize(): void;
|
|
23
28
|
openDevTools(): void;
|
|
24
29
|
closeDevTools(): void;
|
|
30
|
+
setIcon(icon: Icon): void;
|
|
25
31
|
setSize(width: number, height: number): void;
|
|
26
32
|
getSize(): import("@webviewjs/webview").Dimensions;
|
|
27
33
|
setPosition(x: number, y: number): void;
|
|
28
34
|
getPosition(): import("@webviewjs/webview").Position;
|
|
29
35
|
isFocused(): boolean;
|
|
30
36
|
focus(): void;
|
|
37
|
+
tell(message: string, data: any): void;
|
|
31
38
|
hide(): void;
|
|
32
39
|
show(): void;
|
|
33
40
|
close(): void;
|
|
@@ -51,9 +58,18 @@ declare class WindowPool {
|
|
|
51
58
|
__injectCode(window: Window, code: string): Promise<void>;
|
|
52
59
|
__injectControlFunctions(windowObj: Window): Promise<void>;
|
|
53
60
|
__createNewWindowObj(): Promise<Window>;
|
|
54
|
-
createWindow(
|
|
61
|
+
createWindow(options?: {
|
|
62
|
+
visible?: boolean;
|
|
63
|
+
decoration?: boolean;
|
|
64
|
+
title?: string;
|
|
65
|
+
icon?: Icon;
|
|
66
|
+
resizable?: boolean;
|
|
67
|
+
width?: number;
|
|
68
|
+
height?: number;
|
|
69
|
+
}): Promise<Window>;
|
|
55
70
|
closeWindow(window: Window): Promise<void>;
|
|
56
71
|
handle(event: string, callback: (data: any) => any): Promise<void>;
|
|
57
72
|
unhandle(event: string, callback: (data: any) => any): Promise<void>;
|
|
73
|
+
broadcast(event: string, data: any): Promise<void>;
|
|
58
74
|
}
|
|
59
75
|
export { WindowPool, Window };
|
package/src/WindowManager.js
CHANGED
|
@@ -19,6 +19,36 @@ class Window {
|
|
|
19
19
|
this.isDecorated = false;
|
|
20
20
|
this.id = id;
|
|
21
21
|
}
|
|
22
|
+
setLevel(level) {
|
|
23
|
+
if (level == -1) {
|
|
24
|
+
this.window.setAlwaysOnTop(false);
|
|
25
|
+
this.window.setAlwaysOnBottom(true);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
else if (level == 0) {
|
|
29
|
+
this.window.setAlwaysOnTop(false);
|
|
30
|
+
this.window.setAlwaysOnBottom(false);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
else if (level == 1) {
|
|
34
|
+
this.window.setAlwaysOnTop(true);
|
|
35
|
+
this.window.setAlwaysOnBottom(false);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
setFullScreen(isFullScreen, options) {
|
|
40
|
+
if (isFullScreen) {
|
|
41
|
+
if (options?.borderless) {
|
|
42
|
+
this.window.setFullscreen(1);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
this.window.setFullscreen(0);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
this.window.setFullscreen(null);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
22
52
|
setDecorated(isDecorated) {
|
|
23
53
|
this.window.setDecorations(isDecorated);
|
|
24
54
|
this.isDecorated = isDecorated;
|
|
@@ -26,7 +56,7 @@ class Window {
|
|
|
26
56
|
setTitle(title) {
|
|
27
57
|
this.window.setTitle(title);
|
|
28
58
|
}
|
|
29
|
-
|
|
59
|
+
setResizable(resizable) {
|
|
30
60
|
this.window.setResizable(resizable);
|
|
31
61
|
}
|
|
32
62
|
maximize() {
|
|
@@ -69,6 +99,9 @@ class Window {
|
|
|
69
99
|
closeDevTools() {
|
|
70
100
|
this.webview.closeDevtools();
|
|
71
101
|
}
|
|
102
|
+
setIcon(icon) {
|
|
103
|
+
this.window.setWindowIcon(icon.data, icon.width, icon.height);
|
|
104
|
+
}
|
|
72
105
|
setSize(width, height) {
|
|
73
106
|
this.window.setSize(width, height);
|
|
74
107
|
}
|
|
@@ -88,6 +121,9 @@ class Window {
|
|
|
88
121
|
this.unMinimize();
|
|
89
122
|
this.window.focus();
|
|
90
123
|
}
|
|
124
|
+
tell(message, data) {
|
|
125
|
+
this.webview.evaluateScript(`window.dispatchEvent(new CustomEvent('${message}', { detail: ${JSON.stringify(data)} }));`);
|
|
126
|
+
}
|
|
91
127
|
hide() {
|
|
92
128
|
this.window.hide();
|
|
93
129
|
this.isShow = false;
|
|
@@ -325,7 +361,7 @@ class WindowPool {
|
|
|
325
361
|
return await new Promise((resolve) => {
|
|
326
362
|
setImmediate(() => {
|
|
327
363
|
const window = this.app.createBrowserWindow({
|
|
328
|
-
title: "Nexfep",
|
|
364
|
+
title: "Nexfep Window",
|
|
329
365
|
visible: false,
|
|
330
366
|
focused: false,
|
|
331
367
|
});
|
|
@@ -337,13 +373,14 @@ class WindowPool {
|
|
|
337
373
|
const dataText = data.body.toString();
|
|
338
374
|
const dataObj = JSON.parse(dataText);
|
|
339
375
|
if (dataObj.type == "NexfepBeforeUnload") {
|
|
340
|
-
webview.evaluateScript(`
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
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
|
+
}`);
|
|
347
384
|
}
|
|
348
385
|
else if (dataObj.type == "NexfepLoadFalse") {
|
|
349
386
|
this.__injectControlFunctions(windowObj);
|
|
@@ -383,14 +420,10 @@ class WindowPool {
|
|
|
383
420
|
handlers.forEach(async (handler) => {
|
|
384
421
|
const result = await handler(dataObj.data);
|
|
385
422
|
if (result) {
|
|
386
|
-
webview.evaluateScript(`
|
|
387
|
-
window.dispatchEvent(new CustomEvent('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: ${JSON.stringify(result)} }));
|
|
388
|
-
`);
|
|
423
|
+
webview.evaluateScript(`window.dispatchEvent(new CustomEvent('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: ${JSON.stringify(result)} }));`);
|
|
389
424
|
}
|
|
390
425
|
else {
|
|
391
|
-
webview.evaluateScript(`
|
|
392
|
-
window.dispatchEvent(new CustomEvent('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: undefined }));
|
|
393
|
-
`);
|
|
426
|
+
webview.evaluateScript(`window.dispatchEvent(new CustomEvent('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: undefined }));`);
|
|
394
427
|
}
|
|
395
428
|
});
|
|
396
429
|
}
|
|
@@ -399,16 +432,12 @@ class WindowPool {
|
|
|
399
432
|
}
|
|
400
433
|
else if (dataObj.type == "NexfepGetGlobal") {
|
|
401
434
|
const value = this.global.get(dataObj.name);
|
|
402
|
-
webview.evaluateScript(`
|
|
403
|
-
window.dispatchEvent(new CustomEvent('nexfep-get-global-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: ${JSON.stringify(value)} }));
|
|
404
|
-
`);
|
|
435
|
+
webview.evaluateScript(`window.dispatchEvent(new CustomEvent('nexfep-get-global-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: ${JSON.stringify(value)} }));`);
|
|
405
436
|
}
|
|
406
437
|
else if (dataObj.type == "NexfepBroadcast") {
|
|
407
438
|
this.windows.forEach(async (w) => {
|
|
408
439
|
if (w != windowObj && w.isOpen) {
|
|
409
|
-
w.webview.evaluateScript(`
|
|
410
|
-
window.dispatchEvent(new CustomEvent('${dataObj.name}', { detail: ${JSON.stringify(dataObj.data)} }));
|
|
411
|
-
`);
|
|
440
|
+
w.webview.evaluateScript(`window.dispatchEvent(new CustomEvent('${dataObj.name}', { detail: ${JSON.stringify(dataObj.data)} }));`);
|
|
412
441
|
}
|
|
413
442
|
});
|
|
414
443
|
}
|
|
@@ -418,9 +447,7 @@ class WindowPool {
|
|
|
418
447
|
}
|
|
419
448
|
this.windows.forEach(async (w) => {
|
|
420
449
|
if (w.id == dataObj.to) {
|
|
421
|
-
w.webview.evaluateScript(`
|
|
422
|
-
window.dispatchEvent(new CustomEvent('${dataObj.message}', { detail: ${JSON.stringify(dataObj.data)} }));
|
|
423
|
-
`);
|
|
450
|
+
w.webview.evaluateScript(`window.dispatchEvent(new CustomEvent('${dataObj.message}', { detail: ${JSON.stringify(dataObj.data)} }));`);
|
|
424
451
|
}
|
|
425
452
|
});
|
|
426
453
|
}
|
|
@@ -444,16 +471,22 @@ class WindowPool {
|
|
|
444
471
|
});
|
|
445
472
|
});
|
|
446
473
|
}
|
|
447
|
-
async createWindow(
|
|
474
|
+
async createWindow(options) {
|
|
448
475
|
const window = this.windows.find((w) => w.isOpen === false) || (await this.__createNewWindowObj());
|
|
449
476
|
this.freeWindowCount--;
|
|
450
477
|
if (window) {
|
|
451
478
|
window.isOpen = true;
|
|
452
|
-
window.isShow =
|
|
453
|
-
window.setDecorated(
|
|
454
|
-
if (
|
|
479
|
+
window.isShow = options?.visible ?? true;
|
|
480
|
+
window.setDecorated(options?.decoration ?? true);
|
|
481
|
+
if (options?.visible ?? true) {
|
|
455
482
|
window.show();
|
|
456
483
|
}
|
|
484
|
+
window.setTitle(options?.title ?? "Nexfep Window");
|
|
485
|
+
if (options?.icon) {
|
|
486
|
+
window.setIcon(options?.icon);
|
|
487
|
+
}
|
|
488
|
+
window.setResizable(options?.resizable ?? true);
|
|
489
|
+
window.setSize(options?.width ?? 800, options?.height ?? 600);
|
|
457
490
|
}
|
|
458
491
|
if (this.freeWindowCount == 0) {
|
|
459
492
|
this.__createNewWindowObj();
|
|
@@ -479,5 +512,12 @@ class WindowPool {
|
|
|
479
512
|
async unhandle(event, callback) {
|
|
480
513
|
this.handlers.set(event, (this.handlers.get(event) || []).filter((c) => c !== callback));
|
|
481
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
|
+
}
|
|
482
522
|
}
|
|
483
523
|
export { WindowPool, Window };
|