plusui-native-core 0.1.91 → 0.1.95
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/Core/Features/API/browser-api.ts +0 -2
- package/Core/Features/API/index.ts +48 -154
- package/Core/Features/API/window-api.ts +7 -52
- package/Core/Features/Browser/browser.ts +1 -59
- package/Core/Features/Router/router.ts +0 -13
- package/Core/Features/Window/window.ts +52 -180
- package/package.json +1 -1
|
@@ -18,8 +18,6 @@
|
|
|
18
18
|
* browser.canGoBack() - Check if back navigation is possible
|
|
19
19
|
* browser.canGoForward() - Check if forward navigation is possible
|
|
20
20
|
* browser.isLoading() - Check if a page is currently loading
|
|
21
|
-
* browser.emit(name, payload) - Send a message on a browser feature channel
|
|
22
|
-
* browser.on(name, cb) - Listen on a browser feature channel
|
|
23
21
|
*
|
|
24
22
|
* Events:
|
|
25
23
|
* browser.onNavigate(cb) - Fires when navigation occurs (URL change)
|
|
@@ -1,216 +1,110 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* PlusUI API -
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* window.minimize();
|
|
9
|
-
* clipboard.setText('hello');
|
|
10
|
-
* window.onResize((size) => { ... });
|
|
11
|
-
*
|
|
12
|
-
* 2. CUSTOM CHANNELS - Use .on() and .emit()
|
|
13
|
-
* const search = createChannel('search');
|
|
14
|
-
* search.emit({ query: 'test' });
|
|
15
|
-
* search.on((result) => { ... });
|
|
16
|
-
*
|
|
17
|
-
* The `plusui connect` CLI scans your codebase for name.on() and name.emit()
|
|
18
|
-
* and generates typed channel objects for both frontend and backend.
|
|
2
|
+
* PlusUI API - Simple & Direct
|
|
3
|
+
*
|
|
4
|
+
* window.show(), window.hide(), window.close()
|
|
5
|
+
* window.maximize(), window.minimize(), window.restore()
|
|
6
|
+
* window.setSize(w, h), window.setSize(x, y)
|
|
7
|
+
* window.setTitle(title), window.center()
|
|
19
8
|
*/
|
|
20
9
|
|
|
21
|
-
// ============================================================
|
|
22
|
-
// INTERNAL: Initialize Native Bridge Polyfill
|
|
23
|
-
// ============================================================
|
|
24
10
|
if (typeof window !== 'undefined') {
|
|
25
11
|
const win = window as any;
|
|
26
12
|
if (!win.__invoke__) {
|
|
27
|
-
const pendingPromises = new Map<string, { resolve: (val: any) => void; reject: (err: any) => void }>();
|
|
28
13
|
let callId = 0;
|
|
14
|
+
const pending = new Map<string, { resolve: (v: any) => void; reject: (e: any) => void }>();
|
|
29
15
|
|
|
30
16
|
win.__response__ = function (id: string, result: any, error?: any) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
reject(new Error(error));
|
|
36
|
-
} else {
|
|
37
|
-
resolve(result);
|
|
38
|
-
}
|
|
17
|
+
const p = pending.get(id);
|
|
18
|
+
if (p) {
|
|
19
|
+
pending.delete(id);
|
|
20
|
+
error ? p.reject(new Error(error)) : p.resolve(result);
|
|
39
21
|
}
|
|
40
22
|
};
|
|
41
23
|
|
|
42
24
|
win.__invoke__ = function (method: string, params: any[] = []): Promise<any> {
|
|
43
25
|
if (!win.__native_invoke__) {
|
|
44
|
-
console.warn(`[PlusUI] API not initialized: __native_invoke__ missing. Running in mock mode for '${method}'.`);
|
|
45
26
|
return Promise.resolve(null);
|
|
46
27
|
}
|
|
47
28
|
return new Promise((resolve, reject) => {
|
|
48
29
|
const id = String(++callId);
|
|
49
|
-
|
|
50
|
-
|
|
30
|
+
pending.set(id, { resolve, reject });
|
|
51
31
|
try {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
params
|
|
57
|
-
});
|
|
58
|
-
win.__native_invoke__(payload);
|
|
59
|
-
} catch (err) {
|
|
60
|
-
pendingPromises.delete(id);
|
|
61
|
-
reject(err);
|
|
32
|
+
win.__native_invoke__(JSON.stringify({ id, method, params }));
|
|
33
|
+
} catch (e) {
|
|
34
|
+
pending.delete(id);
|
|
35
|
+
reject(e);
|
|
62
36
|
}
|
|
63
37
|
});
|
|
64
38
|
};
|
|
65
39
|
}
|
|
66
40
|
}
|
|
67
41
|
|
|
68
|
-
// ============================================================
|
|
69
|
-
// BUILT-IN FEATURES - Direct methods only (NO .on/.emit)
|
|
70
|
-
// Each feature has its own dedicated API file in this directory.
|
|
71
|
-
// ============================================================
|
|
72
|
-
|
|
73
42
|
export { window } from './window-api';
|
|
74
43
|
export { clipboard } from './clipboard-api';
|
|
44
|
+
export { app } from './app-api';
|
|
45
|
+
export { browser } from './browser-api';
|
|
46
|
+
export { router } from './router-api';
|
|
75
47
|
export { keyboard, KeyCode, KeyMod } from './keyboard-api';
|
|
76
48
|
export { tray } from './tray-api';
|
|
77
49
|
export { display } from './display-api';
|
|
78
|
-
export { fileDrop } from './filedrop-api';
|
|
50
|
+
export { fileDrop, formatFileSize } from './filedrop-api';
|
|
79
51
|
export { menu } from './menu-api';
|
|
80
|
-
export { app } from './app-api';
|
|
81
52
|
export { gpu, GPUBufferUsage, GPUTextureUsage, GPUMapMode, GPUShaderStage, GPUColorWrite } from './webgpu-api';
|
|
82
|
-
export { browser } from './browser-api';
|
|
83
|
-
export { router } from './router-api';
|
|
84
|
-
|
|
85
|
-
// ============================================================
|
|
86
|
-
// CUSTOM CHANNELS - For user-defined events (uses .on/.emit)
|
|
87
|
-
// ============================================================
|
|
88
53
|
|
|
89
|
-
export {
|
|
90
|
-
connect,
|
|
91
|
-
createChannel,
|
|
92
|
-
createFeatureConnect,
|
|
93
|
-
type Channel
|
|
94
|
-
} from './Connect_API';
|
|
95
|
-
|
|
96
|
-
// Internal export for connection generator
|
|
54
|
+
export { connect, createChannel, type Channel } from './Connect_API';
|
|
97
55
|
export { _client } from '../Connection/connect';
|
|
98
56
|
|
|
99
|
-
|
|
100
|
-
// TYPES - Re-exported for convenience
|
|
101
|
-
// ============================================================
|
|
102
|
-
|
|
103
|
-
export type {
|
|
104
|
-
WindowSize,
|
|
105
|
-
WindowPosition,
|
|
106
|
-
WindowRect,
|
|
107
|
-
WindowState,
|
|
108
|
-
WindowId
|
|
109
|
-
} from './window-api';
|
|
110
|
-
|
|
57
|
+
export type { WindowSize, WindowPosition, WindowRect } from './window-api';
|
|
111
58
|
export type { ClipboardAPI } from './clipboard-api';
|
|
112
|
-
|
|
113
|
-
export type {
|
|
114
|
-
KeyEvent,
|
|
115
|
-
Shortcut,
|
|
116
|
-
KeyEventCallback,
|
|
117
|
-
ShortcutCallback,
|
|
118
|
-
} from './keyboard-api';
|
|
119
|
-
|
|
59
|
+
export type { KeyEvent, Shortcut } from './keyboard-api';
|
|
120
60
|
export type { TrayMenuItem, TrayIconData } from './tray-api';
|
|
121
|
-
|
|
122
|
-
export type {
|
|
123
|
-
|
|
124
|
-
DisplayMode,
|
|
125
|
-
DisplayBounds,
|
|
126
|
-
DisplayResolution
|
|
127
|
-
} from './display-api';
|
|
128
|
-
|
|
129
|
-
export type { FileInfo, DragEvent, FileDropAPI } from './filedrop-api';
|
|
130
|
-
|
|
131
|
-
export type {
|
|
132
|
-
MenuItem,
|
|
133
|
-
MenuItemType,
|
|
134
|
-
MenuBarData,
|
|
135
|
-
ContextMenuOptions,
|
|
136
|
-
ContextInfo
|
|
137
|
-
} from './menu-api';
|
|
138
|
-
|
|
61
|
+
export type { Display, DisplayMode, DisplayBounds, DisplayResolution } from './display-api';
|
|
62
|
+
export type { FileInfo, FileDropAPI } from './filedrop-api';
|
|
63
|
+
export type { MenuItem, MenuItemType, MenuBarData, ContextMenuOptions, ContextInfo } from './menu-api';
|
|
139
64
|
export type { AppConfig } from './app-api';
|
|
140
|
-
|
|
141
|
-
export type {
|
|
142
|
-
GPUAdapter,
|
|
143
|
-
GPUDevice,
|
|
144
|
-
GPUBuffer,
|
|
145
|
-
GPUTexture,
|
|
146
|
-
GPUShaderModule,
|
|
147
|
-
GPURenderPipeline,
|
|
148
|
-
GPUComputePipeline,
|
|
149
|
-
GPUQueue,
|
|
150
|
-
GPUCommandEncoder
|
|
151
|
-
} from './webgpu-api';
|
|
152
|
-
|
|
153
|
-
export type {
|
|
154
|
-
BrowserState,
|
|
155
|
-
NavigateCallback,
|
|
156
|
-
StateCallback,
|
|
157
|
-
LoadCallback,
|
|
158
|
-
ErrorCallback,
|
|
159
|
-
} from './browser-api';
|
|
160
|
-
|
|
65
|
+
export type { GPUAdapter, GPUDevice, GPUBuffer, GPUTexture, GPUShaderModule, GPURenderPipeline, GPUComputePipeline, GPUQueue, GPUCommandEncoder } from './webgpu-api';
|
|
66
|
+
export type { BrowserState, NavigateCallback, StateCallback, LoadCallback, ErrorCallback } from './browser-api';
|
|
161
67
|
export type { RouteMap, RouteChangeCallback, RouteConfig } from './router-api';
|
|
162
68
|
|
|
163
|
-
|
|
164
|
-
// HELPER FUNCTIONS
|
|
165
|
-
// ============================================================
|
|
166
|
-
|
|
167
|
-
export {
|
|
168
|
-
readFileAsText,
|
|
169
|
-
readFileAsDataUrl,
|
|
170
|
-
filterFilesByExtension,
|
|
171
|
-
filterFilesByMimeType,
|
|
172
|
-
isImageFile,
|
|
173
|
-
isVideoFile,
|
|
174
|
-
isAudioFile,
|
|
175
|
-
isTextFile,
|
|
176
|
-
formatFileSize
|
|
177
|
-
} from './filedrop-api';
|
|
178
|
-
|
|
179
|
-
// ============================================================
|
|
180
|
-
// DEFAULT EXPORT - For `import plusui from 'plusui'` convenience
|
|
181
|
-
// ============================================================
|
|
69
|
+
export { readFileAsText, readFileAsDataUrl, filterFilesByExtension, filterFilesByMimeType, isImageFile, isVideoFile, isAudioFile, isTextFile } from './filedrop-api';
|
|
182
70
|
|
|
183
71
|
import { window } from './window-api';
|
|
184
72
|
import { clipboard } from './clipboard-api';
|
|
185
|
-
import {
|
|
73
|
+
import { app } from './app-api';
|
|
74
|
+
import { browser } from './browser-api';
|
|
75
|
+
import { router } from './router-api';
|
|
76
|
+
import { keyboard, KeyCode, KeyMod } from './keyboard-api';
|
|
186
77
|
import { tray } from './tray-api';
|
|
187
78
|
import { display } from './display-api';
|
|
188
79
|
import { fileDrop, formatFileSize } from './filedrop-api';
|
|
189
80
|
import { menu } from './menu-api';
|
|
190
|
-
import {
|
|
191
|
-
import {
|
|
192
|
-
import { browser } from './browser-api';
|
|
193
|
-
import { router } from './router-api';
|
|
194
|
-
import { connect, createChannel, createFeatureConnect } from './Connect_API';
|
|
81
|
+
import { gpu, GPUBufferUsage, GPUTextureUsage, GPUMapMode, GPUShaderStage, GPUColorWrite } from './webgpu-api';
|
|
82
|
+
import { connect, createChannel } from './Connect_API';
|
|
195
83
|
|
|
196
84
|
const plusui = {
|
|
197
85
|
window,
|
|
198
|
-
win: window,
|
|
86
|
+
win: window,
|
|
199
87
|
clipboard,
|
|
88
|
+
app,
|
|
89
|
+
api: app,
|
|
90
|
+
browser,
|
|
91
|
+
router,
|
|
200
92
|
keyboard,
|
|
201
93
|
tray,
|
|
202
94
|
display,
|
|
203
95
|
fileDrop,
|
|
204
96
|
menu,
|
|
205
|
-
app,
|
|
206
|
-
api: app,
|
|
207
97
|
gpu,
|
|
208
|
-
browser,
|
|
209
|
-
router,
|
|
210
98
|
connect,
|
|
211
99
|
createChannel,
|
|
212
|
-
|
|
213
|
-
|
|
100
|
+
formatFileSize,
|
|
101
|
+
KeyCode,
|
|
102
|
+
KeyMod,
|
|
103
|
+
GPUBufferUsage,
|
|
104
|
+
GPUTextureUsage,
|
|
105
|
+
GPUMapMode,
|
|
106
|
+
GPUShaderStage,
|
|
107
|
+
GPUColorWrite,
|
|
214
108
|
};
|
|
215
109
|
|
|
216
110
|
export default plusui;
|
|
@@ -1,52 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Window API
|
|
3
|
-
*
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* window.hide() - Hide the window
|
|
9
|
-
* window.minimize() - Minimize to taskbar
|
|
10
|
-
* window.maximize() - Maximize to screen
|
|
11
|
-
* window.restore() - Restore from minimized/maximized
|
|
12
|
-
* window.close() - Close the window
|
|
13
|
-
* window.center() - Center on screen
|
|
14
|
-
* window.focus() - Bring to front and focus
|
|
15
|
-
* window.setTitle(title) - Set the title bar text
|
|
16
|
-
* window.setSize(w, h) - Resize the window
|
|
17
|
-
* window.setPosition(x,y) - Move the window
|
|
18
|
-
* window.setFullscreen(b) - Enter/exit fullscreen
|
|
19
|
-
* window.setAlwaysOnTop(b)- Pin above other windows
|
|
20
|
-
* window.setResizable(b) - Allow/disallow resizing
|
|
21
|
-
* window.setDecorations(b)- Show/hide title bar and borders
|
|
22
|
-
* window.setTransparency(a)- Set window opacity (0–1)
|
|
23
|
-
* window.setIcon(path) - Set the window icon
|
|
24
|
-
* window.getSize() - Get current size
|
|
25
|
-
* window.getPosition() - Get current position
|
|
26
|
-
* window.getRect() - Get position + size together
|
|
27
|
-
* window.getState() - Get full window state
|
|
28
|
-
* window.isMaximized() - Check if maximized
|
|
29
|
-
* window.isMinimized() - Check if minimized
|
|
30
|
-
* window.isVisible() - Check if visible
|
|
31
|
-
*
|
|
32
|
-
* Events:
|
|
33
|
-
* window.onResize(cb) - Fires when window is resized
|
|
34
|
-
* window.onMove(cb) - Fires when window is moved
|
|
35
|
-
* window.onClose(cb) - Fires when window is closed
|
|
36
|
-
* window.onFocus(cb) - Fires when focus changes
|
|
37
|
-
* window.onStateChange(cb)- Fires on any state change
|
|
38
|
-
* window.onMinimize(cb) - Fires when minimized
|
|
39
|
-
* window.onMaximize(cb) - Fires when maximized
|
|
40
|
-
* window.onRestore(cb) - Fires when restored
|
|
41
|
-
* window.onFileDrop(cb) - Fires when files are dropped onto window
|
|
42
|
-
*/
|
|
43
|
-
|
|
44
|
-
export type {
|
|
45
|
-
WindowSize,
|
|
46
|
-
WindowPosition,
|
|
47
|
-
WindowRect,
|
|
48
|
-
WindowState,
|
|
49
|
-
WindowId,
|
|
50
|
-
} from '../Window/window';
|
|
51
|
-
|
|
52
|
-
export { window } from '../Window/window';
|
|
1
|
+
/**
|
|
2
|
+
* Window API
|
|
3
|
+
* Simple, direct window control - no events, just methods.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type { WindowSize, WindowPosition, WindowRect } from '../Window/window';
|
|
7
|
+
export { window } from '../Window/window';
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { plusui } from "@plusui";
|
|
2
|
-
|
|
3
1
|
export interface BrowserState {
|
|
4
2
|
url: string;
|
|
5
3
|
title: string;
|
|
@@ -37,10 +35,6 @@ const _loadStartCallbacks: LoadCallback[] = [];
|
|
|
37
35
|
const _loadEndCallbacks: LoadCallback[] = [];
|
|
38
36
|
const _loadErrorCallbacks: ErrorCallback[] = [];
|
|
39
37
|
let _currentState: BrowserState = { url: '', title: '', canGoBack: false, canGoForward: false, isLoading: false };
|
|
40
|
-
let _routes: Record<string, string> = {};
|
|
41
|
-
let _currentRoute: string = '/';
|
|
42
|
-
const browserFeatureEvents = connect.feature('browser');
|
|
43
|
-
const routerFeatureEvents = connect.feature('router');
|
|
44
38
|
|
|
45
39
|
// Setup event listeners from native backend
|
|
46
40
|
if (typeof window !== 'undefined') {
|
|
@@ -67,16 +61,6 @@ if (typeof window !== 'undefined') {
|
|
|
67
61
|
}
|
|
68
62
|
|
|
69
63
|
export const browser = {
|
|
70
|
-
connect: browserFeatureEvents,
|
|
71
|
-
|
|
72
|
-
on: <TData = unknown>(name: string, callback: (payload: TData) => void): (() => void) => {
|
|
73
|
-
return browserFeatureEvents.on<TData>(name, callback);
|
|
74
|
-
},
|
|
75
|
-
|
|
76
|
-
emit: <TIn = Record<string, unknown>>(name: string, payload: TIn): void => {
|
|
77
|
-
browserFeatureEvents.emit<TIn>(name, payload);
|
|
78
|
-
},
|
|
79
|
-
|
|
80
64
|
async navigate(url: string): Promise<void> {
|
|
81
65
|
await invoke('browser.navigate', [url]);
|
|
82
66
|
},
|
|
@@ -174,46 +158,4 @@ export const browser = {
|
|
|
174
158
|
}
|
|
175
159
|
};
|
|
176
160
|
|
|
177
|
-
export
|
|
178
|
-
connect: routerFeatureEvents,
|
|
179
|
-
|
|
180
|
-
on: <TData = unknown>(name: string, callback: (payload: TData) => void): (() => void) => {
|
|
181
|
-
return routerFeatureEvents.on<TData>(name, callback);
|
|
182
|
-
},
|
|
183
|
-
|
|
184
|
-
emit: <TIn = Record<string, unknown>>(name: string, payload: TIn): void => {
|
|
185
|
-
routerFeatureEvents.emit<TIn>(name, payload);
|
|
186
|
-
},
|
|
187
|
-
|
|
188
|
-
setRoutes(routes: Record<string, string>): void {
|
|
189
|
-
_routes = routes;
|
|
190
|
-
},
|
|
191
|
-
|
|
192
|
-
getRoutes(): Record<string, string> {
|
|
193
|
-
return { ..._routes };
|
|
194
|
-
},
|
|
195
|
-
|
|
196
|
-
async push(route: string): Promise<void> {
|
|
197
|
-
_currentRoute = route;
|
|
198
|
-
const url = _routes[route] || route;
|
|
199
|
-
await browser.navigate(url);
|
|
200
|
-
},
|
|
201
|
-
|
|
202
|
-
async replace(route: string): Promise<void> {
|
|
203
|
-
_currentRoute = route;
|
|
204
|
-
const url = _routes[route] || route;
|
|
205
|
-
await browser.navigate(url);
|
|
206
|
-
},
|
|
207
|
-
|
|
208
|
-
getCurrentRoute(): string {
|
|
209
|
-
return _currentRoute;
|
|
210
|
-
},
|
|
211
|
-
|
|
212
|
-
async setInitialRoute(route: string): Promise<void> {
|
|
213
|
-
_currentRoute = route;
|
|
214
|
-
const url = _routes[route] || route;
|
|
215
|
-
await browser.navigate(url);
|
|
216
|
-
}
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
export default { browser, router };
|
|
161
|
+
export default browser;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { connect } from '../Connection/connect';
|
|
2
1
|
import type { WindowId } from '../Window/window';
|
|
3
2
|
|
|
4
3
|
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
@@ -20,8 +19,6 @@ let _routes: RouteMap = {};
|
|
|
20
19
|
let _currentRoutes: Record<string, string> = {}; // windowId → current route
|
|
21
20
|
const _routeChangeCallbacks: RouteChangeCallback[] = [];
|
|
22
21
|
|
|
23
|
-
const routerFeatureEvents = connect.feature('router');
|
|
24
|
-
|
|
25
22
|
// ─── Bridge ──────────────────────────────────────────────────────────────────
|
|
26
23
|
|
|
27
24
|
export function setInvokeFn(fn: (method: string, args?: unknown[]) => Promise<unknown>) {
|
|
@@ -52,16 +49,6 @@ if (typeof window !== 'undefined') {
|
|
|
52
49
|
// ─── Router API ──────────────────────────────────────────────────────────────
|
|
53
50
|
|
|
54
51
|
export const router = {
|
|
55
|
-
connect: routerFeatureEvents,
|
|
56
|
-
|
|
57
|
-
on: <TData = unknown>(name: string, callback: (payload: TData) => void): (() => void) => {
|
|
58
|
-
return routerFeatureEvents.on<TData>(name, callback);
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
emit: <TIn = Record<string, unknown>>(name: string, payload: TIn): void => {
|
|
62
|
-
routerFeatureEvents.emit<TIn>(name, payload);
|
|
63
|
-
},
|
|
64
|
-
|
|
65
52
|
/**
|
|
66
53
|
* Define route map — maps route paths to frontend URLs.
|
|
67
54
|
* Works with any frontend router (React Router, TanStack, Solid Router, etc.)
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { connect } from '../Connection/connect';
|
|
2
|
-
|
|
3
1
|
export interface WindowSize {
|
|
4
2
|
width: number;
|
|
5
3
|
height: number;
|
|
@@ -17,191 +15,65 @@ export interface WindowRect {
|
|
|
17
15
|
height: number;
|
|
18
16
|
}
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
isMaximized: boolean;
|
|
23
|
-
isVisible: boolean;
|
|
24
|
-
isFullscreen: boolean;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export type WindowId = string;
|
|
28
|
-
|
|
29
|
-
let _invoke: ((method: string, args?: unknown[]) => Promise<unknown>) | null = null;
|
|
30
|
-
let _event: ((event: string, callback: (...args: unknown[]) => void) => () => void) | null = null;
|
|
31
|
-
|
|
32
|
-
export function setInvokeFn(fn: (method: string, args?: unknown[]) => Promise<unknown>) {
|
|
33
|
-
_invoke = fn;
|
|
34
|
-
}
|
|
18
|
+
let callId = 0;
|
|
19
|
+
const pending = new Map<string, { resolve: (v: any) => void; reject: (e: any) => void }>();
|
|
35
20
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (typeof window !== 'undefined' && (window as any).__invoke__) {
|
|
43
|
-
_invoke = (window as any).__invoke__;
|
|
44
|
-
} else {
|
|
45
|
-
throw new Error('Window API not initialized');
|
|
46
|
-
}
|
|
21
|
+
async function invoke<T>(method: string, params: any[] = []): Promise<T> {
|
|
22
|
+
const win = window as any;
|
|
23
|
+
|
|
24
|
+
if (!win.__native_invoke__) {
|
|
25
|
+
console.warn(`[PlusUI] ${method} - native bridge not ready`);
|
|
26
|
+
return null as T;
|
|
47
27
|
}
|
|
48
|
-
return _invoke!(method, args) as Promise<T>;
|
|
49
|
-
}
|
|
50
28
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
const id = String(++callId);
|
|
31
|
+
pending.set(id, { resolve, reject });
|
|
32
|
+
|
|
33
|
+
win.__response__ = (respId: string, result: any, error?: any) => {
|
|
34
|
+
const p = pending.get(respId);
|
|
35
|
+
if (p) {
|
|
36
|
+
pending.delete(respId);
|
|
37
|
+
error ? p.reject(new Error(error)) : p.resolve(result);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
win.__native_invoke__(JSON.stringify({ id, method, params }));
|
|
43
|
+
} catch (e) {
|
|
44
|
+
pending.delete(id);
|
|
45
|
+
reject(e);
|
|
57
46
|
}
|
|
58
|
-
}
|
|
59
|
-
return _event!(event, callback);
|
|
47
|
+
});
|
|
60
48
|
}
|
|
61
49
|
|
|
62
50
|
export const window = {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
await invoke('window.center', id ? [id] : []);
|
|
90
|
-
},
|
|
91
|
-
|
|
92
|
-
async setTitle(title: string, id?: WindowId): Promise<void> {
|
|
93
|
-
const args = id ? [title, id] : [title];
|
|
94
|
-
await invoke('window.setTitle', args);
|
|
95
|
-
},
|
|
96
|
-
|
|
97
|
-
async setSize(width: number, height: number, id?: WindowId): Promise<void> {
|
|
98
|
-
const args = id ? [width, height, id] : [width, height];
|
|
99
|
-
await invoke('window.setSize', args);
|
|
100
|
-
},
|
|
101
|
-
|
|
102
|
-
async setPosition(x: number, y: number, id?: WindowId): Promise<void> {
|
|
103
|
-
const args = id ? [x, y, id] : [x, y];
|
|
104
|
-
await invoke('window.setPosition', args);
|
|
105
|
-
},
|
|
106
|
-
|
|
107
|
-
async setFullscreen(enabled: boolean, id?: WindowId): Promise<void> {
|
|
108
|
-
const args = id ? [enabled, id] : [enabled];
|
|
109
|
-
await invoke('window.setFullscreen', args);
|
|
110
|
-
},
|
|
111
|
-
|
|
112
|
-
async setAlwaysOnTop(enabled: boolean, id?: WindowId): Promise<void> {
|
|
113
|
-
const args = id ? [enabled, id] : [enabled];
|
|
114
|
-
await invoke('window.setAlwaysOnTop', args);
|
|
115
|
-
},
|
|
116
|
-
|
|
117
|
-
async setResizable(enabled: boolean, id?: WindowId): Promise<void> {
|
|
118
|
-
const args = id ? [enabled, id] : [enabled];
|
|
119
|
-
await invoke('window.setResizable', args);
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
async setDecorations(enabled: boolean, id?: WindowId): Promise<void> {
|
|
123
|
-
const args = id ? [enabled, id] : [enabled];
|
|
124
|
-
await invoke('window.setDecorations', args);
|
|
125
|
-
},
|
|
126
|
-
|
|
127
|
-
async setTransparency(alpha: number, id?: WindowId): Promise<void> {
|
|
128
|
-
const args = id ? [alpha, id] : [alpha];
|
|
129
|
-
await invoke('window.setTransparency', args);
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
async getSize(id?: WindowId): Promise<WindowSize> {
|
|
133
|
-
return invoke<WindowSize>('window.getSize', id ? [id] : []);
|
|
134
|
-
},
|
|
135
|
-
|
|
136
|
-
async getPosition(id?: WindowId): Promise<WindowPosition> {
|
|
137
|
-
return invoke<WindowPosition>('window.getPosition', id ? [id] : []);
|
|
138
|
-
},
|
|
139
|
-
|
|
140
|
-
async getRect(id?: WindowId): Promise<WindowRect> {
|
|
141
|
-
return invoke<WindowRect>('window.getRect', id ? [id] : []);
|
|
142
|
-
},
|
|
143
|
-
|
|
144
|
-
async getState(id?: WindowId): Promise<WindowState> {
|
|
145
|
-
return invoke<WindowState>('window.getState', id ? [id] : []);
|
|
146
|
-
},
|
|
147
|
-
|
|
148
|
-
async isMaximized(id?: WindowId): Promise<boolean> {
|
|
149
|
-
return invoke<boolean>('window.isMaximized', id ? [id] : []);
|
|
150
|
-
},
|
|
151
|
-
|
|
152
|
-
async isMinimized(id?: WindowId): Promise<boolean> {
|
|
153
|
-
return invoke<boolean>('window.isMinimized', id ? [id] : []);
|
|
154
|
-
},
|
|
155
|
-
|
|
156
|
-
async isVisible(id?: WindowId): Promise<boolean> {
|
|
157
|
-
return invoke<boolean>('window.isVisible', id ? [id] : []);
|
|
158
|
-
},
|
|
159
|
-
|
|
160
|
-
async focus(id?: WindowId): Promise<void> {
|
|
161
|
-
await invoke('window.focus', id ? [id] : []);
|
|
162
|
-
},
|
|
163
|
-
|
|
164
|
-
async setIcon(iconPath: string, id?: WindowId): Promise<void> {
|
|
165
|
-
const args = id ? [iconPath, id] : [iconPath];
|
|
166
|
-
await invoke('window.setIcon', args);
|
|
167
|
-
},
|
|
168
|
-
|
|
169
|
-
// Direct event registration
|
|
170
|
-
onResize(callback: (size: WindowSize) => void): () => void {
|
|
171
|
-
return eventHandler('window:resize', callback as (...args: unknown[]) => void);
|
|
172
|
-
},
|
|
173
|
-
|
|
174
|
-
onMove(callback: (pos: WindowPosition) => void): () => void {
|
|
175
|
-
return eventHandler('window:move', callback as (...args: unknown[]) => void);
|
|
176
|
-
},
|
|
177
|
-
|
|
178
|
-
onClose(callback: () => void): () => void {
|
|
179
|
-
return eventHandler('window:close', callback as (...args: unknown[]) => void);
|
|
180
|
-
},
|
|
181
|
-
|
|
182
|
-
onFocus(callback: (focused: boolean) => void): () => void {
|
|
183
|
-
return eventHandler('window:focus', callback as (...args: unknown[]) => void);
|
|
184
|
-
},
|
|
185
|
-
|
|
186
|
-
onStateChange(callback: (state: WindowState) => void): () => void {
|
|
187
|
-
return eventHandler('window:stateChange', callback as (...args: unknown[]) => void);
|
|
188
|
-
},
|
|
189
|
-
|
|
190
|
-
onMinimize(callback: () => void): () => void {
|
|
191
|
-
return eventHandler('window:minimize', callback as (...args: unknown[]) => void);
|
|
192
|
-
},
|
|
193
|
-
|
|
194
|
-
onMaximize(callback: () => void): () => void {
|
|
195
|
-
return eventHandler('window:maximize', callback as (...args: unknown[]) => void);
|
|
196
|
-
},
|
|
197
|
-
|
|
198
|
-
onRestore(callback: () => void): () => void {
|
|
199
|
-
return eventHandler('window:restore', callback as (...args: unknown[]) => void);
|
|
200
|
-
},
|
|
201
|
-
|
|
202
|
-
onFileDrop(callback: (files: { path: string; name: string; type: string; size: number }[]) => void): () => void {
|
|
203
|
-
return eventHandler('window:fileDrop', callback as (...args: unknown[]) => void);
|
|
204
|
-
},
|
|
51
|
+
show: () => invoke('window.show'),
|
|
52
|
+
hide: () => invoke('window.hide'),
|
|
53
|
+
close: () => invoke('window.close'),
|
|
54
|
+
minimize: () => invoke('window.minimize'),
|
|
55
|
+
maximize: () => invoke('window.maximize'),
|
|
56
|
+
restore: () => invoke('window.restore'),
|
|
57
|
+
focus: () => invoke('window.focus'),
|
|
58
|
+
center: () => invoke('window.center'),
|
|
59
|
+
|
|
60
|
+
setTitle: (title: string) => invoke('window.setTitle', [title]),
|
|
61
|
+
setSize: (width: number, height: number) => invoke('window.setSize', [width, height]),
|
|
62
|
+
setPosition: (x: number, y: number) => invoke('window.setPosition', [x, y]),
|
|
63
|
+
setFullscreen: (enabled: boolean) => invoke('window.setFullscreen', [enabled]),
|
|
64
|
+
setAlwaysOnTop: (enabled: boolean) => invoke('window.setAlwaysOnTop', [enabled]),
|
|
65
|
+
setResizable: (enabled: boolean) => invoke('window.setResizable', [enabled]),
|
|
66
|
+
setDecorations: (enabled: boolean) => invoke('window.setDecorations', [enabled]),
|
|
67
|
+
setTransparency: (alpha: number) => invoke('window.setTransparency', [alpha]),
|
|
68
|
+
setIcon: (path: string) => invoke('window.setIcon', [path]),
|
|
69
|
+
|
|
70
|
+
getSize: (): Promise<WindowSize> => invoke('window.getSize'),
|
|
71
|
+
getPosition: (): Promise<WindowPosition> => invoke('window.getPosition'),
|
|
72
|
+
getRect: (): Promise<WindowRect> => invoke('window.getRect'),
|
|
73
|
+
|
|
74
|
+
isMaximized: (): Promise<boolean> => invoke('window.isMaximized'),
|
|
75
|
+
isMinimized: (): Promise<boolean> => invoke('window.isMinimized'),
|
|
76
|
+
isVisible: (): Promise<boolean> => invoke('window.isVisible'),
|
|
205
77
|
};
|
|
206
78
|
|
|
207
79
|
export default window;
|