nexfep 0.1.1 → 0.1.3

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.
Files changed (6) hide show
  1. package/LICENSE +20 -20
  2. package/README-CN.md +323 -285
  3. package/README.md +323 -285
  4. package/index.d.ts +46 -45
  5. package/index.js +152 -127
  6. package/package.json +35 -36
package/index.d.ts CHANGED
@@ -1,45 +1,46 @@
1
- import { BrowserWindow, Webview } from "@webviewjs/webview";
2
- declare class Window {
3
- window: BrowserWindow;
4
- webview: Webview;
5
- isOpen: boolean;
6
- isShow: boolean;
7
- isDecorated: boolean;
8
- id: number;
9
- private myPool;
10
- constructor(window: BrowserWindow, webview: Webview, id: number, myPool: WindowPool);
11
- setDecorated(isDecorated: boolean): void;
12
- setTitle(title: string): void;
13
- resizable(resizable: boolean): void;
14
- maximize(): void;
15
- minimize(): void;
16
- unMaximize(): void;
17
- unMinimize(): void;
18
- openDevTools(): void;
19
- closeDevTools(): void;
20
- hide(): void;
21
- show(): void;
22
- close(): void;
23
- loadURL(url: string): Promise<void>;
24
- loadHTML(html: string): Promise<void>;
25
- }
26
- declare class WindowPool {
27
- onCustomMessage: (window: Window, data: string) => void;
28
- private app;
29
- private windows;
30
- private handlers;
31
- private injectCount;
32
- private windowCount;
33
- private freeWindowCount;
34
- constructor(WindowsWebview2UserDataFolder?: string);
35
- __injectCode(window: Window, code: string): Promise<void>;
36
- __injectControlFunctions(windowObj: Window): Promise<void>;
37
- __createNewWindowObj(): Promise<Window>;
38
- createWindow(isShow?: boolean, isDecorated?: boolean): Promise<Window>;
39
- closeWindow(window: Window): Promise<void>;
40
- closePool(): Promise<void>;
41
- handle(event: string, callback: (data: any) => any): Promise<void>;
42
- unhandle(event: string, callback: (data: any) => any): Promise<void>;
43
- mainloop(): void;
44
- }
45
- export { WindowPool, Window };
1
+ import { BrowserWindow, Webview } from "@webviewjs/webview";
2
+ declare class Window {
3
+ window: BrowserWindow;
4
+ webview: Webview;
5
+ isOpen: boolean;
6
+ isShow: boolean;
7
+ isDecorated: boolean;
8
+ id: number;
9
+ private myPool;
10
+ constructor(window: BrowserWindow, webview: Webview, id: number, myPool: WindowPool);
11
+ setDecorated(isDecorated: boolean): void;
12
+ setTitle(title: string): void;
13
+ resizable(resizable: boolean): void;
14
+ maximize(): void;
15
+ minimize(): void;
16
+ unMaximize(): void;
17
+ unMinimize(): void;
18
+ openDevTools(): void;
19
+ closeDevTools(): void;
20
+ hide(): void;
21
+ show(): void;
22
+ close(): void;
23
+ loadURL(url: string): Promise<void>;
24
+ loadHTML(html: string): Promise<void>;
25
+ }
26
+ declare class WindowPool {
27
+ onCustomMessage: (window: Window, data: string) => void;
28
+ private app;
29
+ private windows;
30
+ private handlers;
31
+ private injectCount;
32
+ private windowCount;
33
+ private freeWindowCount;
34
+ global: Map<string, any>;
35
+ constructor(WindowsWebview2UserDataFolder?: string);
36
+ __injectCode(window: Window, code: string): Promise<void>;
37
+ __injectControlFunctions(windowObj: Window): Promise<void>;
38
+ __createNewWindowObj(): Promise<Window>;
39
+ createWindow(isShow?: boolean, isDecorated?: boolean): Promise<Window>;
40
+ closeWindow(window: Window): Promise<void>;
41
+ closePool(): Promise<void>;
42
+ handle(event: string, callback: (data: any) => any): Promise<void>;
43
+ unhandle(event: string, callback: (data: any) => any): Promise<void>;
44
+ mainloop(): void;
45
+ }
46
+ export { WindowPool, Window };
package/index.js CHANGED
@@ -63,10 +63,8 @@ class Window {
63
63
  await this.myPool.__injectControlFunctions(this);
64
64
  }
65
65
  async loadHTML(html) {
66
- console.log("Before loadHTML");
67
66
  await this.webview.loadHtml(html);
68
67
  await this.myPool.__injectControlFunctions(this);
69
- console.log("After loadHTML");
70
68
  }
71
69
  }
72
70
  class WindowPool {
@@ -77,6 +75,7 @@ class WindowPool {
77
75
  injectCount;
78
76
  windowCount;
79
77
  freeWindowCount;
78
+ global;
80
79
  constructor(WindowsWebview2UserDataFolder = path.join(process.env.LOCALAPPDATA || os.homedir(), 'NexfepDevelopment.webview2-data')) {
81
80
  if (os.platform() === 'win32') {
82
81
  // 设置 WebView2 用户数据目录(仅 Windows 需要此配置)
@@ -85,7 +84,6 @@ class WindowPool {
85
84
  fs.mkdirSync(userDataDir, { recursive: true });
86
85
  }
87
86
  process.env.WEBVIEW2_USER_DATA_FOLDER = userDataDir;
88
- console.log('WebView2 user data folder:', userDataDir);
89
87
  }
90
88
  this.onCustomMessage = (window, data) => {
91
89
  console.log('Get Custom Message:', data, "from window", window.id);
@@ -96,128 +94,146 @@ class WindowPool {
96
94
  this.windows = [];
97
95
  this.windowCount = 0;
98
96
  this.freeWindowCount = 0;
97
+ this.global = new Map();
99
98
  }
100
99
  async __injectCode(window, code) {
101
100
  await window.webview.evaluateScript(code);
102
101
  }
103
102
  async __injectControlFunctions(windowObj) {
104
- console.log("Create INJECT_CODE");
105
- const INJECT_CSS = `
106
- [nexfep-area-drag],
107
- [nexfep-area-drag] * {
108
- -webkit-app-region: drag;
109
- app-region: drag;
110
- }
111
-
112
- [nexfep-element-drag] {
113
- -webkit-app-region: drag;
114
- app-region: drag;
115
- }
116
-
117
- [nexfep-no-drag],
118
- [nexfep-no-drag] * {
119
- -webkit-app-region: no-drag !important;
120
- app-region: no-drag !important;
121
- }
122
-
123
- [nexfep-auto-drag],
124
- [nexfep-auto-drag] * {
125
- -webkit-app-region: drag;
126
- app-region: drag;
127
- }
128
-
129
- [nexfep-auto-drag] button,
130
- [nexfep-auto-drag] input,
131
- [nexfep-auto-drag] select,
132
- [nexfep-auto-drag] textarea,
133
- [nexfep-auto-drag] a {
134
- -webkit-app-region: no-drag;
135
- app-region: no-drag;
136
- }
103
+ const INJECT_CSS = `
104
+ [nexfep-area-drag],
105
+ [nexfep-area-drag] * {
106
+ -webkit-app-region: drag;
107
+ app-region: drag;
108
+ }
109
+
110
+ [nexfep-element-drag] {
111
+ -webkit-app-region: drag;
112
+ app-region: drag;
113
+ }
114
+
115
+ [nexfep-no-drag],
116
+ [nexfep-no-drag] * {
117
+ -webkit-app-region: no-drag !important;
118
+ app-region: no-drag !important;
119
+ }
120
+
121
+ [nexfep-auto-drag],
122
+ [nexfep-auto-drag] * {
123
+ -webkit-app-region: drag;
124
+ app-region: drag;
125
+ }
126
+
127
+ [nexfep-auto-drag] button,
128
+ [nexfep-auto-drag] input,
129
+ [nexfep-auto-drag] select,
130
+ [nexfep-auto-drag] textarea,
131
+ [nexfep-auto-drag] a {
132
+ -webkit-app-region: no-drag;
133
+ app-region: no-drag;
134
+ }
137
135
  `;
138
- const INJECT_CODE = `
139
- // 事件监听
140
- window.addEventListener("beforeunload", () => {
141
- const MessageBody = { type: 'NexfepBeforeUnload' }
142
- window.ipc.postMessage(JSON.stringify(MessageBody));
143
- });
144
-
145
- // 窗口控制函数
146
- window.close = () => {
147
- const MessageBody = { type: 'NexfepCloseWindow' }
148
- window.ipc.postMessage(JSON.stringify(MessageBody));
149
- };
150
-
151
- window.minimize = () => {
152
- const MessageBody = { type: 'NexfepMinimizeWindow' }
153
- window.ipc.postMessage(JSON.stringify(MessageBody));
154
- };
155
-
156
- window.unminimize = () => {
157
- const MessageBody = { type: 'NexfepUnMinimizeWindow' }
158
- window.ipc.postMessage(JSON.stringify(MessageBody));
159
- };
160
-
161
- window.maximize = () => {
162
- const MessageBody = { type: 'NexfepMaximizeWindow' }
163
- window.ipc.postMessage(JSON.stringify(MessageBody));
164
- };
165
-
166
- window.unmaximize = () => {
167
- const MessageBody = { type: 'NexfepUnMaximizeWindow' }
168
- window.ipc.postMessage(JSON.stringify(MessageBody));
169
- };
170
- window.setTitle = (title) => {
171
- const MessageBody = { type: 'NexfepSetTitle', title: title }
172
- window.ipc.postMessage(JSON.stringify(MessageBody));
173
- };
174
-
175
- window.openDevTools = () => {
176
- const MessageBody = { type: 'NexfepOpenDevTools' }
177
- window.ipc.postMessage(JSON.stringify(MessageBody));
178
- };
179
-
180
- window.closeDevTools = () => {
181
- const MessageBody = { type: 'NexfepCloseDevTools' }
182
- window.ipc.postMessage(JSON.stringify(MessageBody));
183
- };
184
-
185
- window.postMessage = (data) => {
186
- const MessageBody = { type: 'CustomMessage', data: data }
187
- window.ipc.postMessage(JSON.stringify(MessageBody));
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
- }
206
-
207
- // 注入 CSS 样式
208
- const style = document.createElement('style');
209
- style.textContent = \`${INJECT_CSS}\`;
210
- document.head.appendChild(style);
211
-
212
- // 标记加载完成
213
- window.isNexfepLoadDone = true;
214
-
215
- // 触发加载完成事件
216
- window.dispatchEvent(new Event('nexfep-load-done'));
136
+ const INJECT_CODE = `
137
+ // 事件监听
138
+ window.addEventListener("beforeunload", () => {
139
+ const MessageBody = { type: 'NexfepBeforeUnload' }
140
+ window.ipc.postMessage(JSON.stringify(MessageBody));
141
+ });
142
+
143
+ // 窗口控制函数
144
+ window.close = () => {
145
+ const MessageBody = { type: 'NexfepCloseWindow' }
146
+ window.ipc.postMessage(JSON.stringify(MessageBody));
147
+ };
148
+
149
+ window.minimize = () => {
150
+ const MessageBody = { type: 'NexfepMinimizeWindow' }
151
+ window.ipc.postMessage(JSON.stringify(MessageBody));
152
+ };
153
+
154
+ window.unminimize = () => {
155
+ const MessageBody = { type: 'NexfepUnMinimizeWindow' }
156
+ window.ipc.postMessage(JSON.stringify(MessageBody));
157
+ };
158
+
159
+ window.maximize = () => {
160
+ const MessageBody = { type: 'NexfepMaximizeWindow' }
161
+ window.ipc.postMessage(JSON.stringify(MessageBody));
162
+ };
163
+
164
+ window.unmaximize = () => {
165
+ const MessageBody = { type: 'NexfepUnMaximizeWindow' }
166
+ window.ipc.postMessage(JSON.stringify(MessageBody));
167
+ };
168
+ window.setTitle = (title) => {
169
+ const MessageBody = { type: 'NexfepSetTitle', title: title }
170
+ window.ipc.postMessage(JSON.stringify(MessageBody));
171
+ };
172
+
173
+ window.openDevTools = () => {
174
+ const MessageBody = { type: 'NexfepOpenDevTools' }
175
+ window.ipc.postMessage(JSON.stringify(MessageBody));
176
+ };
177
+
178
+ window.closeDevTools = () => {
179
+ const MessageBody = { type: 'NexfepCloseDevTools' }
180
+ window.ipc.postMessage(JSON.stringify(MessageBody));
181
+ };
182
+
183
+ window.postMessage = (data) => {
184
+ const MessageBody = { type: 'CustomMessage', data: data }
185
+ window.ipc.postMessage(JSON.stringify(MessageBody));
186
+ };
187
+
188
+ window.eventCount = 0;
189
+
190
+ window.invoke = async (event, data) => {
191
+ const MessageBody = { type: 'NexfepInvoke', eventId: [${this.injectCount}, ++window.eventCount], event: event, data: data }
192
+ window.ipc.postMessage(JSON.stringify(MessageBody));
193
+ return new Promise((resolve, reject) => {
194
+ window.addEventListener("nexfep-invoke-result-"+${this.injectCount}+"-"+window.eventCount, (event) => {
195
+ window.removeEventListener("nexfep-invoke-result-"+${this.injectCount}+"-"+window.eventCount, event);
196
+ if(event.detail){
197
+ resolve(event.detail);
198
+ }else{
199
+ resolve();
200
+ }
201
+ });
202
+ });
203
+ }
204
+
205
+ window.setGlobal = (name, value) => {
206
+ const MessageBody = { type: 'NexfepSetGlobal', name: name, value: value }
207
+ window.ipc.postMessage(JSON.stringify(MessageBody));
208
+ }
209
+
210
+ window.getGlobal = (name) => {
211
+ const MessageBody = { type: 'NexfepGetGlobal', eventId: [${this.injectCount}, ++window.eventCount], name: name }
212
+ window.ipc.postMessage(JSON.stringify(MessageBody));
213
+ return new Promise((resolve, reject) => {
214
+ window.addEventListener("nexfep-get-global-result-"+${this.injectCount}+"-"+window.eventCount, (event) => {
215
+ window.removeEventListener("nexfep-get-global-result-"+${this.injectCount}+"-"+window.eventCount, event);
216
+ if(event.detail){
217
+ resolve(event.detail);
218
+ }else{
219
+ resolve();
220
+ }
221
+ });
222
+ });
223
+ }
224
+
225
+ // 注入 CSS 样式
226
+ const style = document.createElement('style');
227
+ style.textContent = \`${INJECT_CSS}\`;
228
+ document.head.appendChild(style);
229
+
230
+ // 标记加载完成
231
+ window.isNexfepLoadDone = true;
232
+
233
+ // 触发加载完成事件
234
+ window.dispatchEvent(new Event('nexfep-load-done'));
217
235
  `;
218
- console.log("Before inject code INJECT_CODE");
219
236
  await this.__injectCode(windowObj, INJECT_CODE);
220
- console.log("After inject control functions");
221
237
  }
222
238
  async __createNewWindowObj() {
223
239
  const window = this.app.createBrowserWindow({ title: "Nexfep" });
@@ -230,12 +246,12 @@ class WindowPool {
230
246
  const dataText = data.body.toString();
231
247
  const dataObj = JSON.parse(dataText);
232
248
  if (dataObj.type == 'NexfepBeforeUnload') {
233
- webview.evaluateScript(`if(window?.isNexfepLoadDone){
234
- const MessageBody = { type: 'NexfepBeforeUnload' }
235
- window.ipc.postMessage(JSON.stringify(MessageBody));
236
- }else{
237
- const MessageBody = { type: 'NexfepLoadFalse' }
238
- window.ipc.postMessage(JSON.stringify(MessageBody));
249
+ webview.evaluateScript(`if(window?.isNexfepLoadDone){
250
+ const MessageBody = { type: 'NexfepBeforeUnload' }
251
+ window.ipc.postMessage(JSON.stringify(MessageBody));
252
+ }else{
253
+ const MessageBody = { type: 'NexfepLoadFalse' }
254
+ window.ipc.postMessage(JSON.stringify(MessageBody));
239
255
  }`);
240
256
  }
241
257
  else if (dataObj.type == 'NexfepLoadFalse') {
@@ -273,17 +289,26 @@ class WindowPool {
273
289
  handlers.forEach(async (handler) => {
274
290
  const result = await handler(dataObj.data);
275
291
  if (result) {
276
- webview.evaluateScript(`
277
- window.dispatchEvent(new Event('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: ${JSON.stringify(result)} }));
292
+ webview.evaluateScript(`
293
+ window.dispatchEvent(new Event('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: ${JSON.stringify(result)} }));
278
294
  `);
279
295
  }
280
296
  else {
281
- webview.evaluateScript(`
282
- window.dispatchEvent(new Event('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: undefined }));
297
+ webview.evaluateScript(`
298
+ window.dispatchEvent(new Event('nexfep-invoke-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: undefined }));
283
299
  `);
284
300
  }
285
301
  });
286
302
  }
303
+ else if (dataObj.type == 'NexfepSetGlobal') {
304
+ this.global.set(dataObj.name, dataObj.value);
305
+ }
306
+ else if (dataObj.type == 'NexfepGetGlobal') {
307
+ const value = this.global.get(dataObj.name);
308
+ webview.evaluateScript(`
309
+ window.dispatchEvent(new Event('nexfep-get-global-result-${dataObj.eventId[0]}-${dataObj.eventId[1]}', { detail: ${JSON.stringify(value)} }));
310
+ `);
311
+ }
287
312
  });
288
313
  return windowObj;
289
314
  }
package/package.json CHANGED
@@ -1,37 +1,36 @@
1
- {
2
- "name": "nexfep",
3
- "description": "A desktop application framework based on @webviewjs/webview",
4
- "repository": "https://github.com/nexfteam/Nexfep",
5
- "homepage": "https://github.com/nexfteam/Nexfep#readme",
6
- "bugs": {
7
- "url": "https://github.com/nexfteam/Nexfep/issues"
8
- },
9
- "keywords": [
10
- "desktop",
11
- "application",
12
- "framework",
13
- "@webviewjs/webview",
14
- "webview",
15
- "typescript"
16
- ],
17
- "version": "0.1.1",
18
- "type": "module",
19
- "packageManager": "pnpm@9.15.9",
20
- "main": "./index.js",
21
- "scripts": {
22
- "compile": "tsc"
23
- },
24
- "author": "nexfteam",
25
- "license": "MIT",
26
- "engines": {
27
- "node": ">=20.11.0"
28
- },
29
- "dependencies": {
30
- "@webviewjs/webview": "^0.1.0"
31
- },
32
- "devDependencies": {
33
- "@types/node": "^22.0.0",
34
- "tsx": "^4.0.0",
35
- "typescript": "^5.0.0"
36
- }
1
+ {
2
+ "name": "nexfep",
3
+ "description": "A desktop application framework based on @webviewjs/webview",
4
+ "repository": "https://github.com/nexfteam/Nexfep",
5
+ "homepage": "https://github.com/nexfteam/Nexfep#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/nexfteam/Nexfep/issues"
8
+ },
9
+ "keywords": [
10
+ "desktop",
11
+ "application",
12
+ "framework",
13
+ "@webviewjs/webview",
14
+ "webview",
15
+ "typescript"
16
+ ],
17
+ "version": "0.1.3",
18
+ "type": "module",
19
+ "main": "./index.js",
20
+ "scripts": {
21
+ "compile": "tsc"
22
+ },
23
+ "author": "nexfteam",
24
+ "license": "MIT",
25
+ "engines": {
26
+ "node": ">=20.11.0"
27
+ },
28
+ "dependencies": {
29
+ "@webviewjs/webview": "^0.1.0"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "^22.0.0",
33
+ "tsx": "^4.0.0",
34
+ "typescript": "^5.0.0"
35
+ }
37
36
  }