plusui-native-core 0.1.96 → 0.1.98

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.
@@ -1,45 +1,12 @@
1
1
  /**
2
- * PlusUI API - Simple & Direct
2
+ * PlusUI API
3
3
  *
4
4
  * window.show(), window.hide(), window.close()
5
5
  * window.maximize(), window.minimize(), window.restore()
6
- * window.setSize(w, h), window.setSize(x, y)
7
- * window.setTitle(title), window.center()
6
+ * window.setSize(w, h), window.setPosition(x, y)
8
7
  */
9
8
 
10
- if (typeof window !== 'undefined') {
11
- const win = window as any;
12
- if (!win.__invoke__) {
13
- let callId = 0;
14
- const pending = new Map<string, { resolve: (v: any) => void; reject: (e: any) => void }>();
15
-
16
- win.__response__ = function (id: string, result: any, error?: any) {
17
- const p = pending.get(id);
18
- if (p) {
19
- pending.delete(id);
20
- error ? p.reject(new Error(error)) : p.resolve(result);
21
- }
22
- };
23
-
24
- win.__invoke__ = function (method: string, params: any[] = []): Promise<any> {
25
- if (!win.__native_invoke__) {
26
- return Promise.resolve(null);
27
- }
28
- return new Promise((resolve, reject) => {
29
- const id = String(++callId);
30
- pending.set(id, { resolve, reject });
31
- try {
32
- win.__native_invoke__(JSON.stringify({ id, method, params }));
33
- } catch (e) {
34
- pending.delete(id);
35
- reject(e);
36
- }
37
- });
38
- };
39
- }
40
- }
41
-
42
- export { window } from './window-api';
9
+ export { window, win } from './window-api';
43
10
  export { clipboard } from './clipboard-api';
44
11
  export { app } from './app-api';
45
12
  export { browser } from './browser-api';
@@ -68,7 +35,7 @@ export type { RouteMap, RouteChangeCallback, RouteConfig } from './router-api';
68
35
 
69
36
  export { readFileAsText, readFileAsDataUrl, filterFilesByExtension, filterFilesByMimeType, isImageFile, isVideoFile, isAudioFile, isTextFile } from './filedrop-api';
70
37
 
71
- import { window } from './window-api';
38
+ import { window, win } from './window-api';
72
39
  import { clipboard } from './clipboard-api';
73
40
  import { app } from './app-api';
74
41
  import { browser } from './browser-api';
@@ -83,7 +50,7 @@ import { connect, createChannel } from './Connect_API';
83
50
 
84
51
  const plusui = {
85
52
  window,
86
- win: window,
53
+ win,
87
54
  clipboard,
88
55
  app,
89
56
  api: app,
@@ -1,7 +1,2 @@
1
- /**
2
- * Window API
3
- * Simple, direct window control - no events, just methods.
4
- */
5
-
6
1
  export type { WindowSize, WindowPosition, WindowRect } from '../Window/window';
7
- export { window } from '../Window/window';
2
+ export { window, win } from '../Window/window';
@@ -1,181 +1,52 @@
1
- import { plusui } from "@plusui";
2
-
3
1
  export interface AppConfig {
4
2
  title?: string;
5
3
  width?: number;
6
4
  height?: number;
7
5
  resizable?: boolean;
8
6
  devtools?: boolean;
9
- trayIcon?: string;
10
- trayTooltip?: string;
11
- alwaysOnTop?: boolean;
12
- centered?: boolean;
13
- transparent?: boolean;
14
- decorations?: boolean;
15
- skipTaskbar?: boolean;
16
- scrollbars?: boolean;
17
- enableFileDrop?: boolean;
18
- }
19
-
20
- export interface InvokeOptions {
21
- timeout?: number;
22
- }
23
-
24
- let _invoke: ((name: string, args?: unknown[]) => Promise<unknown>) | null = null;
25
- let _event: ((event: string, callback: (...args: unknown[]) => void) => () => void) | null = null;
26
- let _initialized = false;
27
-
28
- export function setInvokeFn(fn: (name: string, args?: unknown[]) => Promise<unknown>) {
29
- _invoke = fn;
30
- }
31
-
32
- export function setEventFn(fn: (event: string, callback: (...args: unknown[]) => void) => () => void) {
33
- _event = fn;
34
7
  }
35
8
 
36
- function init(): void {
37
- if (_initialized) return;
38
- _initialized = true;
39
-
40
- if (typeof window !== 'undefined') {
41
- const win = window as Window & {
42
- __plusui_listeners__?: Map<string, Set<(...args: unknown[]) => void>>;
43
- };
44
-
45
- win.__plusui_listeners__ = new Map();
9
+ let callId = 0;
10
+ const pending = new Map<string, { resolve: (v: any) => void; reject: (e: any) => void }>();
46
11
 
47
- window.addEventListener('message', (event: MessageEvent) => {
48
- if (event.data?.type === '__plusui_event__') {
49
- const { event: eventName, payload } = event.data;
50
- const listeners = win.__plusui_listeners__?.get(eventName);
51
- if (listeners) {
52
- listeners.forEach(cb => cb(payload));
53
- }
54
- }
55
- });
56
- }
12
+ function getGlobal(): any {
13
+ if (typeof window !== 'undefined') return window;
14
+ if (typeof globalThis !== 'undefined') return globalThis;
15
+ return {};
57
16
  }
58
17
 
59
- async function invoke<T = unknown>(name: string, args?: unknown[], options: InvokeOptions = {}): Promise<T> {
60
- const { timeout = 30000 } = options;
18
+ const g = getGlobal();
61
19
 
62
- if (_invoke) {
63
- return _invoke(name, args) as Promise<T>;
20
+ g.__response__ = function(id: string, result: any, error?: any) {
21
+ const p = pending.get(id);
22
+ if (p) {
23
+ pending.delete(id);
24
+ error ? p.reject(new Error(error)) : p.resolve(result);
64
25
  }
26
+ };
65
27
 
66
- if (typeof window !== 'undefined') {
67
- const win = window as Window & {
68
- __invoke__?: (name: string, args?: unknown[]) => Promise<unknown>;
69
- __native_invoke__?: (request: string) => void;
70
- };
71
- if (win.__invoke__) {
72
- return win.__invoke__(name, args) as Promise<T>;
73
- }
74
- }
75
-
76
- return new Promise((_, reject) => {
77
- setTimeout(() => reject(new Error(`Invocation ${name} timed out`)), timeout);
78
- });
79
- }
80
-
81
- function eventHandler(event: string, callback: (...args: unknown[]) => void): () => void {
82
- init();
28
+ async function invoke<T>(method: string, params: any[] = []): Promise<T> {
29
+ return new Promise((resolve, reject) => {
30
+ const id = String(++callId);
31
+ pending.set(id, { resolve, reject });
32
+ const payload = JSON.stringify({ id, method, params });
83
33
 
84
- if (!_event) {
85
- if (typeof window !== 'undefined' && (window as any).__on__) {
86
- _event = (window as any).__on__;
34
+ if (g.__native_invoke__) {
35
+ g.__native_invoke__(payload);
36
+ } else if (g.chrome && g.chrome.webview && g.chrome.webview.postMessage) {
37
+ g.chrome.webview.postMessage(payload);
87
38
  } else {
88
- const win = window as Window & {
89
- __plusui_listeners__?: Map<string, Set<(...args: unknown[]) => void>>;
90
- };
91
-
92
- if (!win.__plusui_listeners__) {
93
- win.__plusui_listeners__ = new Map();
94
- }
95
-
96
- const listeners = win.__plusui_listeners__!;
97
-
98
- if (!listeners.has(event)) {
99
- listeners.set(event, new Set());
100
- }
101
-
102
- listeners.get(event)!.add(callback);
103
-
104
- return () => {
105
- listeners.get(event)?.delete(callback);
106
- };
39
+ pending.delete(id);
40
+ console.warn('[PlusUI] ' + method + ' - native bridge not ready');
41
+ resolve(null as T);
107
42
  }
108
- }
109
- return _event!(event, callback);
43
+ });
110
44
  }
111
45
 
112
46
  export const app = {
113
- async invoke<T = unknown>(name: string, args?: unknown[], options: InvokeOptions = {}): Promise<T> {
114
- return invoke<T>(name, args, options);
115
- },
116
-
117
- async quit(): Promise<void> {
118
- await invoke('app.quit');
119
- },
120
-
121
- async getVersion(): Promise<string> {
122
- return invoke<string>('app.getVersion');
123
- },
124
-
125
- async getName(): Promise<string> {
126
- return invoke<string>('app.getName');
127
- },
128
-
129
- async getPath(name: 'home' | 'appData' | 'userData' | 'temp' | 'desktop' | 'documents' | 'downloads'): Promise<string> {
130
- return invoke<string>('app.getPath', [name]);
131
- },
132
-
133
- async setBadge(count: number): Promise<void> {
134
- await invoke('app.setBadge', [count]);
135
- },
136
-
137
- async getBadge(): Promise<number> {
138
- return invoke<number>('app.getBadge');
139
- },
140
-
141
- onReady(callback: () => void): () => void {
142
- return eventHandler('app:ready', callback);
143
- },
144
-
145
- onQuit(callback: (reason?: string) => void): () => void {
146
- return eventHandler('app:quit', callback as (...args: unknown[]) => void);
147
- },
148
-
149
- onActivate(callback: () => void): () => void {
150
- return eventHandler('app:activate', callback);
151
- },
152
-
153
- onWindowAllClosed(callback: () => void): () => void {
154
- return eventHandler('app:windowAllClosed', callback);
155
- },
156
-
157
- onSecondInstance(callback: (args: string[], cwd: string) => void): () => void {
158
- return eventHandler('app:secondInstance', callback as (...args: unknown[]) => void);
159
- },
160
-
161
- on(event: string, callback: (...args: unknown[]) => void): () => void {
162
- return eventHandler(event, callback);
163
- },
164
-
165
- once(event: string, callback: (...args: unknown[]) => void): () => void {
166
- const unsubscribe = this.on(event, (...args) => {
167
- unsubscribe();
168
- callback(...args);
169
- });
170
- return unsubscribe;
171
- },
172
-
173
- emit(event: string, payload?: unknown): void {
174
- if (typeof window !== 'undefined') {
175
- const customEvent = new CustomEvent(event, { detail: payload });
176
- window.dispatchEvent(customEvent);
177
- }
178
- },
47
+ quit: () => invoke<void>('app.quit'),
48
+ getVersion: () => invoke<string>('app.getVersion'),
49
+ getName: () => invoke<string>('app.getName'),
179
50
  };
180
51
 
181
52
  export default app;
@@ -18,62 +18,69 @@ export interface WindowRect {
18
18
  let callId = 0;
19
19
  const pending = new Map<string, { resolve: (v: any) => void; reject: (e: any) => void }>();
20
20
 
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;
21
+ function getGlobal() {
22
+ if (typeof window !== 'undefined') return window;
23
+ if (typeof globalThis !== 'undefined') return globalThis as any;
24
+ return {} as any;
25
+ }
26
+
27
+ const g = getGlobal();
28
+
29
+ g.__response__ = function(id: string, result: any, error?: any) {
30
+ const p = pending.get(id);
31
+ if (p) {
32
+ pending.delete(id);
33
+ error ? p.reject(new Error(error)) : p.resolve(result);
27
34
  }
35
+ };
28
36
 
37
+ async function invoke<T>(method: string, params: any[] = []): Promise<T> {
29
38
  return new Promise((resolve, reject) => {
30
39
  const id = String(++callId);
31
40
  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
 
41
- try {
42
- win.__native_invoke__(JSON.stringify({ id, method, params }));
43
- } catch (e) {
42
+ const payload = JSON.stringify({ id, method, params });
43
+
44
+ if (g.__native_invoke__) {
45
+ g.__native_invoke__(payload);
46
+ } else if (g.chrome && g.chrome.webview && g.chrome.webview.postMessage) {
47
+ g.chrome.webview.postMessage(payload);
48
+ } else {
44
49
  pending.delete(id);
45
- reject(e);
50
+ console.warn('[PlusUI] ' + method + ' - native bridge not ready');
51
+ resolve(null as T);
46
52
  }
47
53
  });
48
54
  }
49
55
 
50
- export const window = {
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'),
56
+ export const win = {
57
+ show: () => invoke<void>('window.show'),
58
+ hide: () => invoke<void>('window.hide'),
59
+ close: () => invoke<void>('window.close'),
60
+ minimize: () => invoke<void>('window.minimize'),
61
+ maximize: () => invoke<void>('window.maximize'),
62
+ restore: () => invoke<void>('window.restore'),
63
+ focus: () => invoke<void>('window.focus'),
64
+ center: () => invoke<void>('window.center'),
59
65
 
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]),
66
+ setTitle: (title: string) => invoke<void>('window.setTitle', [title]),
67
+ setSize: (width: number, height: number) => invoke<void>('window.setSize', [width, height]),
68
+ setPosition: (x: number, y: number) => invoke<void>('window.setPosition', [x, y]),
69
+ setFullscreen: (enabled: boolean) => invoke<void>('window.setFullscreen', [enabled]),
70
+ setAlwaysOnTop: (enabled: boolean) => invoke<void>('window.setAlwaysOnTop', [enabled]),
71
+ setResizable: (enabled: boolean) => invoke<void>('window.setResizable', [enabled]),
72
+ setDecorations: (enabled: boolean) => invoke<void>('window.setDecorations', [enabled]),
73
+ setTransparency: (alpha: number) => invoke<void>('window.setTransparency', [alpha]),
74
+ setIcon: (path: string) => invoke<void>('window.setIcon', [path]),
69
75
 
70
- getSize: (): Promise<WindowSize> => invoke('window.getSize'),
71
- getPosition: (): Promise<WindowPosition> => invoke('window.getPosition'),
72
- getRect: (): Promise<WindowRect> => invoke('window.getRect'),
76
+ getSize: () => invoke<WindowSize>('window.getSize'),
77
+ getPosition: () => invoke<WindowPosition>('window.getPosition'),
78
+ getRect: () => invoke<WindowRect>('window.getRect'),
73
79
 
74
- isMaximized: (): Promise<boolean> => invoke('window.isMaximized'),
75
- isMinimized: (): Promise<boolean> => invoke('window.isMinimized'),
76
- isVisible: (): Promise<boolean> => invoke('window.isVisible'),
80
+ isMaximized: () => invoke<boolean>('window.isMaximized'),
81
+ isMinimized: () => invoke<boolean>('window.isMinimized'),
82
+ isVisible: () => invoke<boolean>('window.isVisible'),
77
83
  };
78
84
 
79
- export default window;
85
+ export { win as window };
86
+ export default win;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plusui-native-core",
3
- "version": "0.1.96",
3
+ "version": "0.1.98",
4
4
  "description": "PlusUI Core framework (frontend + backend implementations)",
5
5
  "type": "module",
6
6
  "main": "./Core/Features/API/index.ts",