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/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 };
@@ -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 };
@@ -4,8 +4,8 @@ class Locker {
4
4
  constructor(appName) {
5
5
  this.locker = new SingleInstance(appName);
6
6
  }
7
- lock() {
8
- return this.locker.lock();
7
+ lock(data) {
8
+ return this.locker.lock(data);
9
9
  }
10
10
  unlock() {
11
11
  return this.locker.unlock();
package/src/Tray.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { Application, TrayIcon, TrayIconImage } from "@webviewjs/webview";
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: TrayIconImage | undefined;
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: Uint8Array<ArrayBuffer | SharedArrayBuffer> | number[], width?: number | null | undefined, height?: number | null | undefined): void;
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, width, height) {
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();
@@ -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
- resizable(resizable: boolean): void;
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(isShow?: boolean, isDecorated?: boolean): Promise<Window>;
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 };
@@ -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
- resizable(resizable) {
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(`if(window?.isNexfepLoadDone){
341
- const MessageBody = { type: 'NexfepBeforeUnload' }
342
- window.ipc.postMessage(JSON.stringify(MessageBody));
343
- }else{
344
- const MessageBody = { type: 'NexfepLoadFalse' }
345
- window.ipc.postMessage(JSON.stringify(MessageBody));
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(isShow = true, isDecorated = true) {
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 = isShow;
453
- window.setDecorated(isDecorated);
454
- if (isShow) {
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 };