plusui-native-core 0.1.105 → 0.1.107

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 (77) hide show
  1. package/Core/.cache/clangd/index/api.hpp.016B34C8046EF490.idx +0 -0
  2. package/Core/.cache/clangd/index/app.cpp.1E6FAF043D496421.idx +0 -0
  3. package/Core/.cache/clangd/index/app.hpp.FA0E5D412C4E6148.idx +0 -0
  4. package/Core/.cache/clangd/index/browser.cpp.9461A2CAF129F1D9.idx +0 -0
  5. package/Core/.cache/clangd/index/browser.hpp.BE40AE80881B3107.idx +0 -0
  6. package/Core/.cache/clangd/index/clipboard.cpp.2399913537B2A7AD.idx +0 -0
  7. package/Core/.cache/clangd/index/clipboard.hpp.C1095DDACD7149E9.idx +0 -0
  8. package/Core/.cache/clangd/index/connect.cpp.518C66C7C28B30A9.idx +0 -0
  9. package/Core/.cache/clangd/index/connect.hpp.08E2F7CD13B78601.idx +0 -0
  10. package/Core/.cache/clangd/index/connection.hpp.849FAEF1523BF2C3.idx +0 -0
  11. package/Core/.cache/clangd/index/display.cpp.F6F6D932BF9F8D8E.idx +0 -0
  12. package/Core/.cache/clangd/index/display.hpp.0C1A9CAD11EE4404.idx +0 -0
  13. package/Core/.cache/clangd/index/filedrop.cpp.669B524B3C501C52.idx +0 -0
  14. package/Core/.cache/clangd/index/filedrop.hpp.48460099C3F35F2D.idx +0 -0
  15. package/Core/.cache/clangd/index/keyboard.cpp.DC6D34E4A4F798DD.idx +0 -0
  16. package/Core/.cache/clangd/index/keyboard.hpp.F016CB68D7DE5A46.idx +0 -0
  17. package/Core/.cache/clangd/index/keyboard_linux.cpp.B403FDCEA7A6CA53.idx +0 -0
  18. package/Core/.cache/clangd/index/menu.cpp.3059F08D8D2DF265.idx +0 -0
  19. package/Core/.cache/clangd/index/menu.hpp.8716DCCC573910D4.idx +0 -0
  20. package/Core/.cache/clangd/index/plusui.hpp.8CFCDFDC2E3F41DD.idx +0 -0
  21. package/Core/.cache/clangd/index/router.cpp.EAC9EAD34C59E573.idx +0 -0
  22. package/Core/.cache/clangd/index/router.hpp.2B06E2EE9998468D.idx +0 -0
  23. package/Core/.cache/clangd/index/stb_image.h.E26CF48FE089A0D3.idx +0 -0
  24. package/Core/.cache/clangd/index/tray.cpp.92F244E7E1D7F0EC.idx +0 -0
  25. package/Core/.cache/clangd/index/tray.hpp.0D881B0601BBBD25.idx +0 -0
  26. package/Core/.cache/clangd/index/webgpu.cpp.FC656FA8BE10FE15.idx +0 -0
  27. package/Core/.cache/clangd/index/webgpu.hpp.5AF1A5E9DF9E5AE0.idx +0 -0
  28. package/Core/.cache/clangd/index/window.cpp.191D8C9ADF874B22.idx +0 -0
  29. package/Core/.cache/clangd/index/window.hpp.B9811B43AA295697.idx +0 -0
  30. package/Core/.claude/settings.local.json +7 -0
  31. package/Core/CMakeLists.txt +1 -1
  32. package/Core/Features/API/app-api.ts +28 -28
  33. package/Core/Features/API/browser-api.ts +38 -38
  34. package/Core/Features/API/clipboard-api.ts +21 -21
  35. package/Core/Features/API/display-api.ts +33 -33
  36. package/Core/Features/API/keyboard-api.ts +33 -33
  37. package/Core/Features/API/menu-api.ts +39 -39
  38. package/Core/Features/API/router-api.ts +23 -23
  39. package/Core/Features/API/tray-api.ts +22 -22
  40. package/Core/Features/API/webgpu-api.ts +55 -55
  41. package/Core/Features/App/app.cpp +135 -102
  42. package/Core/Features/Browser/browser.cpp +227 -227
  43. package/Core/Features/Browser/browser.ts +161 -161
  44. package/Core/Features/Clipboard/clipboard.cpp +235 -235
  45. package/Core/Features/Display/display.cpp +212 -212
  46. package/Core/Features/FileDrop/filedrop.cpp +448 -324
  47. package/Core/Features/FileDrop/filedrop.css +421 -421
  48. package/Core/Features/FileDrop/filedrop.ts +0 -7
  49. package/Core/Features/Keyboard/keyboard_linux.cpp +4 -0
  50. package/Core/Features/Router/router.cpp +62 -62
  51. package/Core/Features/Router/router.ts +113 -113
  52. package/Core/Features/Tray/tray.cpp +437 -324
  53. package/Core/Features/WebGPU/webgpu.cpp +948 -948
  54. package/Core/Features/Window/webview.cpp +1009 -1009
  55. package/Core/Features/Window/webview.ts +516 -516
  56. package/Core/Features/Window/window.cpp +2240 -1986
  57. package/Core/include/plusui/api.hpp +237 -237
  58. package/Core/include/plusui/app.hpp +36 -34
  59. package/Core/include/plusui/browser.hpp +67 -67
  60. package/Core/include/plusui/clipboard.hpp +41 -41
  61. package/Core/include/plusui/connect.hpp +340 -340
  62. package/Core/include/plusui/connection.hpp +3 -3
  63. package/Core/include/plusui/display.hpp +90 -90
  64. package/Core/include/plusui/filedrop.hpp +92 -77
  65. package/Core/include/plusui/keyboard.hpp +112 -112
  66. package/Core/include/plusui/menu.hpp +153 -153
  67. package/Core/include/plusui/plusui +18 -18
  68. package/Core/include/plusui/router.hpp +42 -42
  69. package/Core/include/plusui/tray.hpp +94 -94
  70. package/Core/include/plusui/webgpu.hpp +434 -434
  71. package/Core/include/plusui/window.hpp +180 -177
  72. package/Core/scripts/generate-umbrella-header.mjs +77 -77
  73. package/Core/vendor/WebView2EnvironmentOptions.h +406 -406
  74. package/Core/vendor/webview.h +487 -487
  75. package/Core/vendor/webview2.h +52079 -52079
  76. package/README.md +19 -19
  77. package/package.json +1 -1
@@ -1,516 +1,516 @@
1
- /**
2
- * WebView API - Web content rendering and JavaScript execution
3
- *
4
- * Provides comprehensive webview operations including:
5
- * - HTML/URL loading
6
- * - JavaScript execution and bidirectional communication
7
- * - Navigation controls
8
- * - Dev tools integration
9
- * - CSS injection and customization
10
- * - Event handling for page lifecycle
11
- */
12
-
13
- export interface WebViewConfig {
14
- userAgent?: string;
15
- devtools?: boolean;
16
- contextMenu?: boolean;
17
- javascript?: boolean;
18
- webSecurity?: boolean;
19
- allowFileAccess?: boolean;
20
- allowRemoteContent?: boolean;
21
- dataPath?: string;
22
- cacheSize?: number; // MB
23
- disableWebviewDragDrop?: boolean; // Disable browser HTML drag-drop (auto-set by WindowConfig.fileDrop)
24
- }
25
-
26
- export type WindowId = number;
27
-
28
- export interface WebViewAPI {
29
- // Initialization
30
- initialize(windowId: WindowId, config?: WebViewConfig): Promise<void>;
31
-
32
- // Content loading
33
- loadURL(url: string): Promise<void>;
34
- loadHTML(html: string, baseURL?: string): Promise<void>;
35
- loadFile(filePath: string): Promise<void>;
36
-
37
- // Navigation
38
- reload(): Promise<void>;
39
- reloadIgnoringCache(): Promise<void>;
40
- stop(): Promise<void>;
41
- goBack(): Promise<void>;
42
- goForward(): Promise<void>;
43
- goToOffset(offset: number): Promise<void>;
44
- canGoBack(): Promise<boolean>;
45
- canGoForward(): Promise<boolean>;
46
- clearHistory(): Promise<void>;
47
-
48
- // JavaScript execution
49
- executeScript(script: string): Promise<void>;
50
- executeScriptWithResult<T = any>(script: string): Promise<T>;
51
- executeScriptAsync(script: string): Promise<void>;
52
-
53
- // JavaScript bindings
54
- bind(name: string, callback: (...args: any[]) => any): Promise<void>;
55
- unbind(name: string): Promise<void>;
56
- unbindAll(): Promise<void>;
57
-
58
- // IPC - Message passing
59
- postMessage(message: string): Promise<void>;
60
- onMessage(callback: (message: string) => void): () => void;
61
-
62
- // Dev tools
63
- openDevTools(): Promise<void>;
64
- closeDevTools(): Promise<void>;
65
- toggleDevTools(): Promise<void>;
66
- isDevToolsOpen(): Promise<boolean>;
67
-
68
- // Settings
69
- setUserAgent(userAgent: string): Promise<void>;
70
- getUserAgent(): Promise<string>;
71
- setZoom(factor: number): Promise<void>;
72
- getZoom(): Promise<number>;
73
- setBackgroundColor(r: number, g: number, b: number, a?: number): Promise<void>;
74
- setScrollbarsVisible(visible: boolean): Promise<void>;
75
- setWebviewDragDropEnabled(enabled: boolean): Promise<void>; // Runtime toggle for webview drag-drop
76
-
77
- // CSS injection
78
- injectCSS(css: string): Promise<void>;
79
- removeCSS(identifier: string): Promise<void>;
80
-
81
- // JavaScript injection
82
- injectScript(script: string): Promise<void>;
83
- injectScriptAtStart(script: string): Promise<void>;
84
-
85
- // Cache and data
86
- clearCache(): Promise<void>;
87
- clearCookies(): Promise<void>;
88
- clearStorage(): Promise<void>;
89
- setCookie(name: string, value: string, domain?: string): Promise<void>;
90
- getCookie(name: string): Promise<string>;
91
-
92
- // Content control
93
- setHTML(html: string): Promise<void>;
94
- getHTML(): Promise<string>;
95
- setTitle(title: string): Promise<void>;
96
- getTitle(): Promise<string>;
97
-
98
- // Print
99
- print(): Promise<void>;
100
- printToPDF(path: string): Promise<void>;
101
-
102
- // Find in page
103
- find(text: string, forward?: boolean, caseSensitive?: boolean): Promise<void>;
104
- stopFind(clearSelection?: boolean): Promise<void>;
105
-
106
- // Security
107
- setAllowFileAccess(allow: boolean): Promise<void>;
108
- setAllowRemoteContent(allow: boolean): Promise<void>;
109
- setWebSecurity(enabled: boolean): Promise<void>;
110
-
111
- // Download handling
112
- setDownloadPath(path: string): Promise<void>;
113
- getDownloadPath(): Promise<string>;
114
-
115
- // Lifecycle events
116
- onNavigationStart(callback: (url: string) => boolean): () => void; // Return false to cancel
117
- onNavigationComplete(callback: () => void): () => void;
118
- onLoadStart(callback: () => void): () => void;
119
- onLoadEnd(callback: () => void): () => void;
120
- onLoadError(callback: (error: string, code: number) => void): () => void;
121
- onTitleChange(callback: (title: string) => void): () => void;
122
- onURLChange(callback: (url: string) => void): () => void;
123
- onFullscreenChange(callback: (isFullscreen: boolean) => void): () => void;
124
-
125
- // JavaScript events
126
- onConsoleMessage(callback: (message: string, level: number, source: string) => void): () => void;
127
- onScriptError(callback: (error: string, code: number) => void): () => void;
128
-
129
- // Download events
130
- onDownloadStart(callback: (url: string, filename: string) => void): () => void;
131
- onDownloadProgress(callback: (url: string, current: number, total: number) => void): () => void;
132
- onDownloadComplete(callback: (path: string) => void): () => void;
133
-
134
- // Permission events
135
- onPermissionRequest(callback: (origin: string, permission: string) => boolean): () => void;
136
-
137
- // State queries
138
- isLoading(): Promise<boolean>;
139
- getURL(): Promise<string>;
140
- getLoadProgress(): Promise<number>; // 0-100
141
- canExecuteScripts(): Promise<boolean>;
142
- }
143
-
144
- export class WebView implements WebViewAPI {
145
- private invokeFn: (name: string, args?: unknown[]) => Promise<unknown>;
146
- private onFn: (event: string, callback: (data: unknown) => void) => () => void;
147
- private windowId?: WindowId;
148
-
149
- constructor(
150
- invokeFn: (name: string, args?: unknown[]) => Promise<unknown>,
151
- onFn: (event: string, callback: (data: unknown) => void) => () => void,
152
- windowId?: WindowId
153
- ) {
154
- this.invokeFn = invokeFn;
155
- this.onFn = onFn;
156
- this.windowId = windowId;
157
- }
158
-
159
- // Initialization
160
- async initialize(windowId: WindowId, config?: WebViewConfig): Promise<void> {
161
- this.windowId = windowId;
162
- await this.invokeFn('webview.initialize', [windowId, config]);
163
- }
164
-
165
- // Content loading
166
- async loadURL(url: string): Promise<void> {
167
- await this.invokeFn('webview.loadURL', [url]);
168
- }
169
-
170
- async loadHTML(html: string, baseURL?: string): Promise<void> {
171
- if (baseURL) {
172
- await this.invokeFn('webview.loadHTML', [html, baseURL]);
173
- } else {
174
- await this.invokeFn('webview.loadHTML', [html]);
175
- }
176
- }
177
-
178
- async loadFile(filePath: string): Promise<void> {
179
- await this.invokeFn('webview.loadFile', [filePath]);
180
- }
181
-
182
- // Navigation
183
- async reload(): Promise<void> {
184
- await this.invokeFn('webview.reload');
185
- }
186
-
187
- async reloadIgnoringCache(): Promise<void> {
188
- await this.invokeFn('webview.reloadIgnoringCache');
189
- }
190
-
191
- async stop(): Promise<void> {
192
- await this.invokeFn('webview.stop');
193
- }
194
-
195
- async goBack(): Promise<void> {
196
- await this.invokeFn('webview.goBack');
197
- }
198
-
199
- async goForward(): Promise<void> {
200
- await this.invokeFn('webview.goForward');
201
- }
202
-
203
- async goToOffset(offset: number): Promise<void> {
204
- await this.invokeFn('webview.goToOffset', [offset]);
205
- }
206
-
207
- async canGoBack(): Promise<boolean> {
208
- return (await this.invokeFn('webview.canGoBack')) as boolean;
209
- }
210
-
211
- async canGoForward(): Promise<boolean> {
212
- return (await this.invokeFn('webview.canGoForward')) as boolean;
213
- }
214
-
215
- async clearHistory(): Promise<void> {
216
- await this.invokeFn('webview.clearHistory');
217
- }
218
-
219
- // JavaScript execution
220
- async executeScript(script: string): Promise<void> {
221
- await this.invokeFn('webview.executeScript', [script]);
222
- }
223
-
224
- async executeScriptWithResult<T = any>(script: string): Promise<T> {
225
- return (await this.invokeFn('webview.executeScriptWithResult', [script])) as T;
226
- }
227
-
228
- async executeScriptAsync(script: string): Promise<void> {
229
- await this.invokeFn('webview.executeScriptAsync', [script]);
230
- }
231
-
232
- // JavaScript bindings
233
- async bind(name: string, callback: (...args: any[]) => any): Promise<void> {
234
- // Store the callback locally and expose it via IPC
235
- await this.invokeFn('webview.bind', [name]);
236
-
237
- // Handle calls from webview
238
- this.onFn(`webview:call:${name}`, (args: any) => {
239
- const result = callback(...(Array.isArray(args) ? args : [args]));
240
- this.invokeFn('webview.bindResponse', [name, result]);
241
- });
242
- }
243
-
244
- async unbind(name: string): Promise<void> {
245
- await this.invokeFn('webview.unbind', [name]);
246
- }
247
-
248
- async unbindAll(): Promise<void> {
249
- await this.invokeFn('webview.unbindAll');
250
- }
251
-
252
- // IPC
253
- async postMessage(message: string): Promise<void> {
254
- await this.invokeFn('webview.postMessage', [message]);
255
- }
256
-
257
- onMessage(callback: (message: string) => void): () => void {
258
- return this.onFn('webview:message', (data) => {
259
- callback(data as string);
260
- });
261
- }
262
-
263
- // Dev tools
264
- async openDevTools(): Promise<void> {
265
- await this.invokeFn('webview.openDevTools');
266
- }
267
-
268
- async closeDevTools(): Promise<void> {
269
- await this.invokeFn('webview.closeDevTools');
270
- }
271
-
272
- async toggleDevTools(): Promise<void> {
273
- await this.invokeFn('webview.toggleDevTools');
274
- }
275
-
276
- async isDevToolsOpen(): Promise<boolean> {
277
- return (await this.invokeFn('webview.isDevToolsOpen')) as boolean;
278
- }
279
-
280
- // Settings
281
- async setUserAgent(userAgent: string): Promise<void> {
282
- await this.invokeFn('webview.setUserAgent', [userAgent]);
283
- }
284
-
285
- async getUserAgent(): Promise<string> {
286
- return (await this.invokeFn('webview.getUserAgent')) as string;
287
- }
288
-
289
- async setZoom(factor: number): Promise<void> {
290
- await this.invokeFn('webview.setZoom', [factor]);
291
- }
292
-
293
- async getZoom(): Promise<number> {
294
- return (await this.invokeFn('webview.getZoom')) as number;
295
- }
296
-
297
- async setBackgroundColor(r: number, g: number, b: number, a: number = 255): Promise<void> {
298
- await this.invokeFn('webview.setBackgroundColor', [r, g, b, a]);
299
- }
300
-
301
- async setScrollbarsVisible(visible: boolean): Promise<void> {
302
- await this.invokeFn('webview.setScrollbarsVisible', [visible]);
303
- }
304
-
305
- async setWebviewDragDropEnabled(enabled: boolean): Promise<void> {
306
- await this.invokeFn('webview.setWebviewDragDropEnabled', [enabled]);
307
- }
308
-
309
- // CSS injection
310
- async injectCSS(css: string): Promise<void> {
311
- await this.invokeFn('webview.injectCSS', [css]);
312
- }
313
-
314
- async removeCSS(identifier: string): Promise<void> {
315
- await this.invokeFn('webview.removeCSS', [identifier]);
316
- }
317
-
318
- // JavaScript injection
319
- async injectScript(script: string): Promise<void> {
320
- await this.invokeFn('webview.injectScript', [script]);
321
- }
322
-
323
- async injectScriptAtStart(script: string): Promise<void> {
324
- await this.invokeFn('webview.injectScriptAtStart', [script]);
325
- }
326
-
327
- // Cache and data
328
- async clearCache(): Promise<void> {
329
- await this.invokeFn('webview.clearCache');
330
- }
331
-
332
- async clearCookies(): Promise<void> {
333
- await this.invokeFn('webview.clearCookies');
334
- }
335
-
336
- async clearStorage(): Promise<void> {
337
- await this.invokeFn('webview.clearStorage');
338
- }
339
-
340
- async setCookie(name: string, value: string, domain: string = ''): Promise<void> {
341
- await this.invokeFn('webview.setCookie', [name, value, domain]);
342
- }
343
-
344
- async getCookie(name: string): Promise<string> {
345
- return (await this.invokeFn('webview.getCookie', [name])) as string;
346
- }
347
-
348
- // Content control
349
- async setHTML(html: string): Promise<void> {
350
- await this.invokeFn('webview.setHTML', [html]);
351
- }
352
-
353
- async getHTML(): Promise<string> {
354
- return (await this.invokeFn('webview.getHTML')) as string;
355
- }
356
-
357
- async setTitle(title: string): Promise<void> {
358
- await this.invokeFn('webview.setTitle', [title]);
359
- }
360
-
361
- async getTitle(): Promise<string> {
362
- return (await this.invokeFn('webview.getTitle')) as string;
363
- }
364
-
365
- // Print
366
- async print(): Promise<void> {
367
- await this.invokeFn('webview.print');
368
- }
369
-
370
- async printToPDF(path: string): Promise<void> {
371
- await this.invokeFn('webview.printToPDF', [path]);
372
- }
373
-
374
- // Find in page
375
- async find(text: string, forward: boolean = true, caseSensitive: boolean = false): Promise<void> {
376
- await this.invokeFn('webview.find', [text, forward, caseSensitive]);
377
- }
378
-
379
- async stopFind(clearSelection: boolean = true): Promise<void> {
380
- await this.invokeFn('webview.stopFind', [clearSelection]);
381
- }
382
-
383
- // Security
384
- async setAllowFileAccess(allow: boolean): Promise<void> {
385
- await this.invokeFn('webview.setAllowFileAccess', [allow]);
386
- }
387
-
388
- async setAllowRemoteContent(allow: boolean): Promise<void> {
389
- await this.invokeFn('webview.setAllowRemoteContent', [allow]);
390
- }
391
-
392
- async setWebSecurity(enabled: boolean): Promise<void> {
393
- await this.invokeFn('webview.setWebSecurity', [enabled]);
394
- }
395
-
396
- // Download handling
397
- async setDownloadPath(path: string): Promise<void> {
398
- await this.invokeFn('webview.setDownloadPath', [path]);
399
- }
400
-
401
- async getDownloadPath(): Promise<string> {
402
- return (await this.invokeFn('webview.getDownloadPath')) as string;
403
- }
404
-
405
- // Lifecycle events
406
- onNavigationStart(callback: (url: string) => boolean): () => void {
407
- return this.onFn('webview:navigationStart', (data: any) => {
408
- const shouldContinue = callback(data.url);
409
- this.invokeFn('webview.navigationResponse', [shouldContinue]);
410
- });
411
- }
412
-
413
- onNavigationComplete(callback: () => void): () => void {
414
- return this.onFn('webview:navigationComplete', callback);
415
- }
416
-
417
- onLoadStart(callback: () => void): () => void {
418
- return this.onFn('webview:loadStart', callback);
419
- }
420
-
421
- onLoadEnd(callback: () => void): () => void {
422
- return this.onFn('webview:loadEnd', callback);
423
- }
424
-
425
- onLoadError(callback: (error: string, code: number) => void): () => void {
426
- return this.onFn('webview:loadError', (data: any) => {
427
- callback(data.error, data.code);
428
- });
429
- }
430
-
431
- onTitleChange(callback: (title: string) => void): () => void {
432
- return this.onFn('webview:titleChange', (data) => {
433
- callback(data as string);
434
- });
435
- }
436
-
437
- onURLChange(callback: (url: string) => void): () => void {
438
- return this.onFn('webview:urlChange', (data) => {
439
- callback(data as string);
440
- });
441
- }
442
-
443
- onFullscreenChange(callback: (isFullscreen: boolean) => void): () => void {
444
- return this.onFn('webview:fullscreenChange', (data) => {
445
- callback(data as boolean);
446
- });
447
- }
448
-
449
- // JavaScript events
450
- onConsoleMessage(callback: (message: string, level: number, source: string) => void): () => void {
451
- return this.onFn('webview:console', (data: any) => {
452
- callback(data.message, data.level, data.source);
453
- });
454
- }
455
-
456
- onScriptError(callback: (error: string, code: number) => void): () => void {
457
- return this.onFn('webview:scriptError', (data: any) => {
458
- callback(data.error, data.code);
459
- });
460
- }
461
-
462
- // Download events
463
- onDownloadStart(callback: (url: string, filename: string) => void): () => void {
464
- return this.onFn('webview:downloadStart', (data: any) => {
465
- callback(data.url, data.filename);
466
- });
467
- }
468
-
469
- onDownloadProgress(callback: (url: string, current: number, total: number) => void): () => void {
470
- return this.onFn('webview:downloadProgress', (data: any) => {
471
- callback(data.url, data.current, data.total);
472
- });
473
- }
474
-
475
- onDownloadComplete(callback: (path: string) => void): () => void {
476
- return this.onFn('webview:downloadComplete', (data) => {
477
- callback(data as string);
478
- });
479
- }
480
-
481
- // Permission events
482
- onPermissionRequest(callback: (origin: string, permission: string) => boolean): () => void {
483
- return this.onFn('webview:permissionRequest', (data: any) => {
484
- const allowed = callback(data.origin, data.permission);
485
- this.invokeFn('webview.permissionResponse', [allowed]);
486
- });
487
- }
488
-
489
- // State queries
490
- async isLoading(): Promise<boolean> {
491
- return (await this.invokeFn('webview.isLoading')) as boolean;
492
- }
493
-
494
- async getURL(): Promise<string> {
495
- return (await this.invokeFn('webview.getURL')) as string;
496
- }
497
-
498
- async getLoadProgress(): Promise<number> {
499
- return (await this.invokeFn('webview.getLoadProgress')) as number;
500
- }
501
-
502
- async canExecuteScripts(): Promise<boolean> {
503
- return (await this.invokeFn('webview.canExecuteScripts')) as boolean;
504
- }
505
- }
506
-
507
- /**
508
- * Factory function to create WebView instance
509
- */
510
- export function createWebView(
511
- invokeFn: (name: string, args?: unknown[]) => Promise<unknown>,
512
- onFn: (event: string, callback: (data: unknown) => void) => () => void,
513
- windowId?: WindowId
514
- ): WebView {
515
- return new WebView(invokeFn, onFn, windowId);
516
- }
1
+ /**
2
+ * WebView API - Web content rendering and JavaScript execution
3
+ *
4
+ * Provides comprehensive webview operations including:
5
+ * - HTML/URL loading
6
+ * - JavaScript execution and bidirectional communication
7
+ * - Navigation controls
8
+ * - Dev tools integration
9
+ * - CSS injection and customization
10
+ * - Event handling for page lifecycle
11
+ */
12
+
13
+ export interface WebViewConfig {
14
+ userAgent?: string;
15
+ devtools?: boolean;
16
+ contextMenu?: boolean;
17
+ javascript?: boolean;
18
+ webSecurity?: boolean;
19
+ allowFileAccess?: boolean;
20
+ allowRemoteContent?: boolean;
21
+ dataPath?: string;
22
+ cacheSize?: number; // MB
23
+ disableWebviewDragDrop?: boolean; // Disable browser HTML drag-drop (auto-set by WindowConfig.fileDrop)
24
+ }
25
+
26
+ export type WindowId = number;
27
+
28
+ export interface WebViewAPI {
29
+ // Initialization
30
+ initialize(windowId: WindowId, config?: WebViewConfig): Promise<void>;
31
+
32
+ // Content loading
33
+ loadURL(url: string): Promise<void>;
34
+ loadHTML(html: string, baseURL?: string): Promise<void>;
35
+ loadFile(filePath: string): Promise<void>;
36
+
37
+ // Navigation
38
+ reload(): Promise<void>;
39
+ reloadIgnoringCache(): Promise<void>;
40
+ stop(): Promise<void>;
41
+ goBack(): Promise<void>;
42
+ goForward(): Promise<void>;
43
+ goToOffset(offset: number): Promise<void>;
44
+ canGoBack(): Promise<boolean>;
45
+ canGoForward(): Promise<boolean>;
46
+ clearHistory(): Promise<void>;
47
+
48
+ // JavaScript execution
49
+ executeScript(script: string): Promise<void>;
50
+ executeScriptWithResult<T = any>(script: string): Promise<T>;
51
+ executeScriptAsync(script: string): Promise<void>;
52
+
53
+ // JavaScript bindings
54
+ bind(name: string, callback: (...args: any[]) => any): Promise<void>;
55
+ unbind(name: string): Promise<void>;
56
+ unbindAll(): Promise<void>;
57
+
58
+ // IPC - Message passing
59
+ postMessage(message: string): Promise<void>;
60
+ onMessage(callback: (message: string) => void): () => void;
61
+
62
+ // Dev tools
63
+ openDevTools(): Promise<void>;
64
+ closeDevTools(): Promise<void>;
65
+ toggleDevTools(): Promise<void>;
66
+ isDevToolsOpen(): Promise<boolean>;
67
+
68
+ // Settings
69
+ setUserAgent(userAgent: string): Promise<void>;
70
+ getUserAgent(): Promise<string>;
71
+ setZoom(factor: number): Promise<void>;
72
+ getZoom(): Promise<number>;
73
+ setBackgroundColor(r: number, g: number, b: number, a?: number): Promise<void>;
74
+ setScrollbarsVisible(visible: boolean): Promise<void>;
75
+ setWebviewDragDropEnabled(enabled: boolean): Promise<void>; // Runtime toggle for webview drag-drop
76
+
77
+ // CSS injection
78
+ injectCSS(css: string): Promise<void>;
79
+ removeCSS(identifier: string): Promise<void>;
80
+
81
+ // JavaScript injection
82
+ injectScript(script: string): Promise<void>;
83
+ injectScriptAtStart(script: string): Promise<void>;
84
+
85
+ // Cache and data
86
+ clearCache(): Promise<void>;
87
+ clearCookies(): Promise<void>;
88
+ clearStorage(): Promise<void>;
89
+ setCookie(name: string, value: string, domain?: string): Promise<void>;
90
+ getCookie(name: string): Promise<string>;
91
+
92
+ // Content control
93
+ setHTML(html: string): Promise<void>;
94
+ getHTML(): Promise<string>;
95
+ setTitle(title: string): Promise<void>;
96
+ getTitle(): Promise<string>;
97
+
98
+ // Print
99
+ print(): Promise<void>;
100
+ printToPDF(path: string): Promise<void>;
101
+
102
+ // Find in page
103
+ find(text: string, forward?: boolean, caseSensitive?: boolean): Promise<void>;
104
+ stopFind(clearSelection?: boolean): Promise<void>;
105
+
106
+ // Security
107
+ setAllowFileAccess(allow: boolean): Promise<void>;
108
+ setAllowRemoteContent(allow: boolean): Promise<void>;
109
+ setWebSecurity(enabled: boolean): Promise<void>;
110
+
111
+ // Download handling
112
+ setDownloadPath(path: string): Promise<void>;
113
+ getDownloadPath(): Promise<string>;
114
+
115
+ // Lifecycle events
116
+ onNavigationStart(callback: (url: string) => boolean): () => void; // Return false to cancel
117
+ onNavigationComplete(callback: () => void): () => void;
118
+ onLoadStart(callback: () => void): () => void;
119
+ onLoadEnd(callback: () => void): () => void;
120
+ onLoadError(callback: (error: string, code: number) => void): () => void;
121
+ onTitleChange(callback: (title: string) => void): () => void;
122
+ onURLChange(callback: (url: string) => void): () => void;
123
+ onFullscreenChange(callback: (isFullscreen: boolean) => void): () => void;
124
+
125
+ // JavaScript events
126
+ onConsoleMessage(callback: (message: string, level: number, source: string) => void): () => void;
127
+ onScriptError(callback: (error: string, code: number) => void): () => void;
128
+
129
+ // Download events
130
+ onDownloadStart(callback: (url: string, filename: string) => void): () => void;
131
+ onDownloadProgress(callback: (url: string, current: number, total: number) => void): () => void;
132
+ onDownloadComplete(callback: (path: string) => void): () => void;
133
+
134
+ // Permission events
135
+ onPermissionRequest(callback: (origin: string, permission: string) => boolean): () => void;
136
+
137
+ // State queries
138
+ isLoading(): Promise<boolean>;
139
+ getURL(): Promise<string>;
140
+ getLoadProgress(): Promise<number>; // 0-100
141
+ canExecuteScripts(): Promise<boolean>;
142
+ }
143
+
144
+ export class WebView implements WebViewAPI {
145
+ private invokeFn: (name: string, args?: unknown[]) => Promise<unknown>;
146
+ private onFn: (event: string, callback: (data: unknown) => void) => () => void;
147
+ private windowId?: WindowId;
148
+
149
+ constructor(
150
+ invokeFn: (name: string, args?: unknown[]) => Promise<unknown>,
151
+ onFn: (event: string, callback: (data: unknown) => void) => () => void,
152
+ windowId?: WindowId
153
+ ) {
154
+ this.invokeFn = invokeFn;
155
+ this.onFn = onFn;
156
+ this.windowId = windowId;
157
+ }
158
+
159
+ // Initialization
160
+ async initialize(windowId: WindowId, config?: WebViewConfig): Promise<void> {
161
+ this.windowId = windowId;
162
+ await this.invokeFn('webview.initialize', [windowId, config]);
163
+ }
164
+
165
+ // Content loading
166
+ async loadURL(url: string): Promise<void> {
167
+ await this.invokeFn('webview.loadURL', [url]);
168
+ }
169
+
170
+ async loadHTML(html: string, baseURL?: string): Promise<void> {
171
+ if (baseURL) {
172
+ await this.invokeFn('webview.loadHTML', [html, baseURL]);
173
+ } else {
174
+ await this.invokeFn('webview.loadHTML', [html]);
175
+ }
176
+ }
177
+
178
+ async loadFile(filePath: string): Promise<void> {
179
+ await this.invokeFn('webview.loadFile', [filePath]);
180
+ }
181
+
182
+ // Navigation
183
+ async reload(): Promise<void> {
184
+ await this.invokeFn('webview.reload');
185
+ }
186
+
187
+ async reloadIgnoringCache(): Promise<void> {
188
+ await this.invokeFn('webview.reloadIgnoringCache');
189
+ }
190
+
191
+ async stop(): Promise<void> {
192
+ await this.invokeFn('webview.stop');
193
+ }
194
+
195
+ async goBack(): Promise<void> {
196
+ await this.invokeFn('webview.goBack');
197
+ }
198
+
199
+ async goForward(): Promise<void> {
200
+ await this.invokeFn('webview.goForward');
201
+ }
202
+
203
+ async goToOffset(offset: number): Promise<void> {
204
+ await this.invokeFn('webview.goToOffset', [offset]);
205
+ }
206
+
207
+ async canGoBack(): Promise<boolean> {
208
+ return (await this.invokeFn('webview.canGoBack')) as boolean;
209
+ }
210
+
211
+ async canGoForward(): Promise<boolean> {
212
+ return (await this.invokeFn('webview.canGoForward')) as boolean;
213
+ }
214
+
215
+ async clearHistory(): Promise<void> {
216
+ await this.invokeFn('webview.clearHistory');
217
+ }
218
+
219
+ // JavaScript execution
220
+ async executeScript(script: string): Promise<void> {
221
+ await this.invokeFn('webview.executeScript', [script]);
222
+ }
223
+
224
+ async executeScriptWithResult<T = any>(script: string): Promise<T> {
225
+ return (await this.invokeFn('webview.executeScriptWithResult', [script])) as T;
226
+ }
227
+
228
+ async executeScriptAsync(script: string): Promise<void> {
229
+ await this.invokeFn('webview.executeScriptAsync', [script]);
230
+ }
231
+
232
+ // JavaScript bindings
233
+ async bind(name: string, callback: (...args: any[]) => any): Promise<void> {
234
+ // Store the callback locally and expose it via IPC
235
+ await this.invokeFn('webview.bind', [name]);
236
+
237
+ // Handle calls from webview
238
+ this.onFn(`webview:call:${name}`, (args: any) => {
239
+ const result = callback(...(Array.isArray(args) ? args : [args]));
240
+ this.invokeFn('webview.bindResponse', [name, result]);
241
+ });
242
+ }
243
+
244
+ async unbind(name: string): Promise<void> {
245
+ await this.invokeFn('webview.unbind', [name]);
246
+ }
247
+
248
+ async unbindAll(): Promise<void> {
249
+ await this.invokeFn('webview.unbindAll');
250
+ }
251
+
252
+ // IPC
253
+ async postMessage(message: string): Promise<void> {
254
+ await this.invokeFn('webview.postMessage', [message]);
255
+ }
256
+
257
+ onMessage(callback: (message: string) => void): () => void {
258
+ return this.onFn('webview:message', (data) => {
259
+ callback(data as string);
260
+ });
261
+ }
262
+
263
+ // Dev tools
264
+ async openDevTools(): Promise<void> {
265
+ await this.invokeFn('webview.openDevTools');
266
+ }
267
+
268
+ async closeDevTools(): Promise<void> {
269
+ await this.invokeFn('webview.closeDevTools');
270
+ }
271
+
272
+ async toggleDevTools(): Promise<void> {
273
+ await this.invokeFn('webview.toggleDevTools');
274
+ }
275
+
276
+ async isDevToolsOpen(): Promise<boolean> {
277
+ return (await this.invokeFn('webview.isDevToolsOpen')) as boolean;
278
+ }
279
+
280
+ // Settings
281
+ async setUserAgent(userAgent: string): Promise<void> {
282
+ await this.invokeFn('webview.setUserAgent', [userAgent]);
283
+ }
284
+
285
+ async getUserAgent(): Promise<string> {
286
+ return (await this.invokeFn('webview.getUserAgent')) as string;
287
+ }
288
+
289
+ async setZoom(factor: number): Promise<void> {
290
+ await this.invokeFn('webview.setZoom', [factor]);
291
+ }
292
+
293
+ async getZoom(): Promise<number> {
294
+ return (await this.invokeFn('webview.getZoom')) as number;
295
+ }
296
+
297
+ async setBackgroundColor(r: number, g: number, b: number, a: number = 255): Promise<void> {
298
+ await this.invokeFn('webview.setBackgroundColor', [r, g, b, a]);
299
+ }
300
+
301
+ async setScrollbarsVisible(visible: boolean): Promise<void> {
302
+ await this.invokeFn('webview.setScrollbarsVisible', [visible]);
303
+ }
304
+
305
+ async setWebviewDragDropEnabled(enabled: boolean): Promise<void> {
306
+ await this.invokeFn('webview.setWebviewDragDropEnabled', [enabled]);
307
+ }
308
+
309
+ // CSS injection
310
+ async injectCSS(css: string): Promise<void> {
311
+ await this.invokeFn('webview.injectCSS', [css]);
312
+ }
313
+
314
+ async removeCSS(identifier: string): Promise<void> {
315
+ await this.invokeFn('webview.removeCSS', [identifier]);
316
+ }
317
+
318
+ // JavaScript injection
319
+ async injectScript(script: string): Promise<void> {
320
+ await this.invokeFn('webview.injectScript', [script]);
321
+ }
322
+
323
+ async injectScriptAtStart(script: string): Promise<void> {
324
+ await this.invokeFn('webview.injectScriptAtStart', [script]);
325
+ }
326
+
327
+ // Cache and data
328
+ async clearCache(): Promise<void> {
329
+ await this.invokeFn('webview.clearCache');
330
+ }
331
+
332
+ async clearCookies(): Promise<void> {
333
+ await this.invokeFn('webview.clearCookies');
334
+ }
335
+
336
+ async clearStorage(): Promise<void> {
337
+ await this.invokeFn('webview.clearStorage');
338
+ }
339
+
340
+ async setCookie(name: string, value: string, domain: string = ''): Promise<void> {
341
+ await this.invokeFn('webview.setCookie', [name, value, domain]);
342
+ }
343
+
344
+ async getCookie(name: string): Promise<string> {
345
+ return (await this.invokeFn('webview.getCookie', [name])) as string;
346
+ }
347
+
348
+ // Content control
349
+ async setHTML(html: string): Promise<void> {
350
+ await this.invokeFn('webview.setHTML', [html]);
351
+ }
352
+
353
+ async getHTML(): Promise<string> {
354
+ return (await this.invokeFn('webview.getHTML')) as string;
355
+ }
356
+
357
+ async setTitle(title: string): Promise<void> {
358
+ await this.invokeFn('webview.setTitle', [title]);
359
+ }
360
+
361
+ async getTitle(): Promise<string> {
362
+ return (await this.invokeFn('webview.getTitle')) as string;
363
+ }
364
+
365
+ // Print
366
+ async print(): Promise<void> {
367
+ await this.invokeFn('webview.print');
368
+ }
369
+
370
+ async printToPDF(path: string): Promise<void> {
371
+ await this.invokeFn('webview.printToPDF', [path]);
372
+ }
373
+
374
+ // Find in page
375
+ async find(text: string, forward: boolean = true, caseSensitive: boolean = false): Promise<void> {
376
+ await this.invokeFn('webview.find', [text, forward, caseSensitive]);
377
+ }
378
+
379
+ async stopFind(clearSelection: boolean = true): Promise<void> {
380
+ await this.invokeFn('webview.stopFind', [clearSelection]);
381
+ }
382
+
383
+ // Security
384
+ async setAllowFileAccess(allow: boolean): Promise<void> {
385
+ await this.invokeFn('webview.setAllowFileAccess', [allow]);
386
+ }
387
+
388
+ async setAllowRemoteContent(allow: boolean): Promise<void> {
389
+ await this.invokeFn('webview.setAllowRemoteContent', [allow]);
390
+ }
391
+
392
+ async setWebSecurity(enabled: boolean): Promise<void> {
393
+ await this.invokeFn('webview.setWebSecurity', [enabled]);
394
+ }
395
+
396
+ // Download handling
397
+ async setDownloadPath(path: string): Promise<void> {
398
+ await this.invokeFn('webview.setDownloadPath', [path]);
399
+ }
400
+
401
+ async getDownloadPath(): Promise<string> {
402
+ return (await this.invokeFn('webview.getDownloadPath')) as string;
403
+ }
404
+
405
+ // Lifecycle events
406
+ onNavigationStart(callback: (url: string) => boolean): () => void {
407
+ return this.onFn('webview:navigationStart', (data: any) => {
408
+ const shouldContinue = callback(data.url);
409
+ this.invokeFn('webview.navigationResponse', [shouldContinue]);
410
+ });
411
+ }
412
+
413
+ onNavigationComplete(callback: () => void): () => void {
414
+ return this.onFn('webview:navigationComplete', callback);
415
+ }
416
+
417
+ onLoadStart(callback: () => void): () => void {
418
+ return this.onFn('webview:loadStart', callback);
419
+ }
420
+
421
+ onLoadEnd(callback: () => void): () => void {
422
+ return this.onFn('webview:loadEnd', callback);
423
+ }
424
+
425
+ onLoadError(callback: (error: string, code: number) => void): () => void {
426
+ return this.onFn('webview:loadError', (data: any) => {
427
+ callback(data.error, data.code);
428
+ });
429
+ }
430
+
431
+ onTitleChange(callback: (title: string) => void): () => void {
432
+ return this.onFn('webview:titleChange', (data) => {
433
+ callback(data as string);
434
+ });
435
+ }
436
+
437
+ onURLChange(callback: (url: string) => void): () => void {
438
+ return this.onFn('webview:urlChange', (data) => {
439
+ callback(data as string);
440
+ });
441
+ }
442
+
443
+ onFullscreenChange(callback: (isFullscreen: boolean) => void): () => void {
444
+ return this.onFn('webview:fullscreenChange', (data) => {
445
+ callback(data as boolean);
446
+ });
447
+ }
448
+
449
+ // JavaScript events
450
+ onConsoleMessage(callback: (message: string, level: number, source: string) => void): () => void {
451
+ return this.onFn('webview:console', (data: any) => {
452
+ callback(data.message, data.level, data.source);
453
+ });
454
+ }
455
+
456
+ onScriptError(callback: (error: string, code: number) => void): () => void {
457
+ return this.onFn('webview:scriptError', (data: any) => {
458
+ callback(data.error, data.code);
459
+ });
460
+ }
461
+
462
+ // Download events
463
+ onDownloadStart(callback: (url: string, filename: string) => void): () => void {
464
+ return this.onFn('webview:downloadStart', (data: any) => {
465
+ callback(data.url, data.filename);
466
+ });
467
+ }
468
+
469
+ onDownloadProgress(callback: (url: string, current: number, total: number) => void): () => void {
470
+ return this.onFn('webview:downloadProgress', (data: any) => {
471
+ callback(data.url, data.current, data.total);
472
+ });
473
+ }
474
+
475
+ onDownloadComplete(callback: (path: string) => void): () => void {
476
+ return this.onFn('webview:downloadComplete', (data) => {
477
+ callback(data as string);
478
+ });
479
+ }
480
+
481
+ // Permission events
482
+ onPermissionRequest(callback: (origin: string, permission: string) => boolean): () => void {
483
+ return this.onFn('webview:permissionRequest', (data: any) => {
484
+ const allowed = callback(data.origin, data.permission);
485
+ this.invokeFn('webview.permissionResponse', [allowed]);
486
+ });
487
+ }
488
+
489
+ // State queries
490
+ async isLoading(): Promise<boolean> {
491
+ return (await this.invokeFn('webview.isLoading')) as boolean;
492
+ }
493
+
494
+ async getURL(): Promise<string> {
495
+ return (await this.invokeFn('webview.getURL')) as string;
496
+ }
497
+
498
+ async getLoadProgress(): Promise<number> {
499
+ return (await this.invokeFn('webview.getLoadProgress')) as number;
500
+ }
501
+
502
+ async canExecuteScripts(): Promise<boolean> {
503
+ return (await this.invokeFn('webview.canExecuteScripts')) as boolean;
504
+ }
505
+ }
506
+
507
+ /**
508
+ * Factory function to create WebView instance
509
+ */
510
+ export function createWebView(
511
+ invokeFn: (name: string, args?: unknown[]) => Promise<unknown>,
512
+ onFn: (event: string, callback: (data: unknown) => void) => () => void,
513
+ windowId?: WindowId
514
+ ): WebView {
515
+ return new WebView(invokeFn, onFn, windowId);
516
+ }