@bobfrankston/msgapidefs 0.1.0
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/README.md +132 -0
- package/msgapidefs.d.ts +322 -0
- package/msgapidefs.js +110 -0
- package/msgapidefs.ts +427 -0
- package/package.json +39 -0
- package/samples.html +431 -0
package/README.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# @bobfrankston/msgapidefs
|
|
2
|
+
|
|
3
|
+
TypeScript definitions for the **msgapi** JavaScript API used in msgview and msger.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @bobfrankston/msgapidefs
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### TypeScript
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import type { MsgAPI } from '@bobfrankston/msgapidefs';
|
|
17
|
+
import { isMsgAPI, getMsgAPI } from '@bobfrankston/msgapidefs';
|
|
18
|
+
|
|
19
|
+
// Option 1: Type the global window.msgapi
|
|
20
|
+
declare global {
|
|
21
|
+
interface Window {
|
|
22
|
+
msgapi?: MsgAPI;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Check if running in msgview/msger
|
|
27
|
+
if (isMsgAPI()) {
|
|
28
|
+
window.msgapi!.setTitle('My Application');
|
|
29
|
+
window.msgapi!.saveData('lastOpened', new Date().toISOString());
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Option 2: Use getMsgAPI() for cross-platform compatibility
|
|
33
|
+
const msgapi = getMsgAPI();
|
|
34
|
+
msgapi.saveData('userPrefs', { theme: 'dark' }); // Works in both msgview/msger and browser!
|
|
35
|
+
msgapi.setTitle('My App'); // Only works in msgview/msger, no-op in browser
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### JavaScript
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
import { isMsgAPI, getMsgAPI } from '@bobfrankston/msgapidefs';
|
|
42
|
+
|
|
43
|
+
const msgapi = getMsgAPI();
|
|
44
|
+
|
|
45
|
+
// Data persistence (works in both msgview/msger and browser)
|
|
46
|
+
msgapi.saveData('userSettings', { fontSize: 14, theme: 'dark' });
|
|
47
|
+
const settings = msgapi.loadData('userSettings', { fontSize: 12 });
|
|
48
|
+
|
|
49
|
+
// Window control (msgview/msger only, gracefully degrades in browser)
|
|
50
|
+
if (isMsgAPI()) {
|
|
51
|
+
msgapi.toggleFullscreen();
|
|
52
|
+
msgapi.setAlwaysOnTop(true);
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## API Reference
|
|
57
|
+
|
|
58
|
+
### Window Control
|
|
59
|
+
|
|
60
|
+
- `toggleFullscreen()` - Toggle fullscreen mode
|
|
61
|
+
- `setFullscreen(enabled: boolean)` - Set fullscreen state
|
|
62
|
+
- `minimize()` - Minimize window
|
|
63
|
+
- `maximize()` - Toggle maximize/restore
|
|
64
|
+
- `setSize(width, height)` - Set window size
|
|
65
|
+
- `setPosition(x, y)` - Set window position
|
|
66
|
+
- `setAlwaysOnTop(enabled: boolean)` - Keep window on top
|
|
67
|
+
- `setTitle(title: string)` - Set window title
|
|
68
|
+
- `close(result?)` - Close window with optional result
|
|
69
|
+
|
|
70
|
+
### Data Persistence
|
|
71
|
+
|
|
72
|
+
- `saveData(key, value)` - Save data to localStorage
|
|
73
|
+
- `loadData(key, defaultValue?)` - Load data from localStorage
|
|
74
|
+
- `removeData(key)` - Remove data
|
|
75
|
+
- `clearData()` - Clear all msgapi data
|
|
76
|
+
|
|
77
|
+
### File System (Coming Soon)
|
|
78
|
+
|
|
79
|
+
- `fs.selectFile(options?)` - Open file picker
|
|
80
|
+
- `fs.selectFiles(options?)` - Open multi-file picker
|
|
81
|
+
- `fs.saveFileAs(content, filename?, options?)` - Save file dialog
|
|
82
|
+
- `fs.selectFolder(options?)` - Folder picker
|
|
83
|
+
- `fs.read(path)` - Read file (requires allowFs flag)
|
|
84
|
+
- `fs.write(path, content)` - Write file (requires allowFs flag)
|
|
85
|
+
- `fs.list(path)` - List directory (requires allowFs flag)
|
|
86
|
+
- `fs.exists(path)` - Check if file exists (requires allowFs flag)
|
|
87
|
+
- `fs.delete(path)` - Delete file (requires allowFs flag)
|
|
88
|
+
|
|
89
|
+
## Examples
|
|
90
|
+
|
|
91
|
+
See [samples.html](samples.html) for interactive examples and demos of all API features!
|
|
92
|
+
|
|
93
|
+
**Test in msgview:**
|
|
94
|
+
```bash
|
|
95
|
+
msgview -url "file:///path/to/node_modules/@bobfrankston/msgapidefs/samples.html"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Test in msger:**
|
|
99
|
+
```bash
|
|
100
|
+
msger -url "file:///path/to/node_modules/@bobfrankston/msgapidefs/samples.html"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Test in browser:**
|
|
104
|
+
```bash
|
|
105
|
+
# Open samples.html in your browser to test browser compatibility
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The samples demonstrate:
|
|
109
|
+
- Window control (fullscreen, minimize, maximize, resize, position)
|
|
110
|
+
- Data persistence (save/load user preferences, session data, recent files)
|
|
111
|
+
- Presentation mode example
|
|
112
|
+
- Session management
|
|
113
|
+
- And more!
|
|
114
|
+
|
|
115
|
+
## Browser Compatibility
|
|
116
|
+
|
|
117
|
+
The `getMsgAPI()` function returns a browser-compatible implementation:
|
|
118
|
+
|
|
119
|
+
- **Data persistence**: Uses localStorage in both msgview/msger and browser
|
|
120
|
+
- **Window control**: No-op in browser (except `setTitle` updates document.title)
|
|
121
|
+
- **File system**: Not available in browser (`fs` is undefined)
|
|
122
|
+
|
|
123
|
+
This allows you to write code once that works in both environments!
|
|
124
|
+
|
|
125
|
+
## Related Packages
|
|
126
|
+
|
|
127
|
+
- [@bobfrankston/msgview](https://www.npmjs.com/package/@bobfrankston/msgview) - Electron-based message box (slower, works on Pi)
|
|
128
|
+
- [@bobfrankston/msger](https://www.npmjs.com/package/@bobfrankston/msger) - Rust/wry-based message box (fast, lightweight)
|
|
129
|
+
|
|
130
|
+
## License
|
|
131
|
+
|
|
132
|
+
ISC
|
package/msgapidefs.d.ts
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript definitions for the msgapi JavaScript API
|
|
3
|
+
*
|
|
4
|
+
* This module provides type-safe access to msgapi's window control,
|
|
5
|
+
* data persistence, and file system features (used by msgview and msger).
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import type { MsgAPI } from '@bobfrankston/msgapidefs';
|
|
10
|
+
*
|
|
11
|
+
* declare global {
|
|
12
|
+
* interface Window {
|
|
13
|
+
* msgapi?: MsgAPI;
|
|
14
|
+
* }
|
|
15
|
+
* }
|
|
16
|
+
*
|
|
17
|
+
* // Check if running in msgview/msger
|
|
18
|
+
* if (window.msgapi) {
|
|
19
|
+
* window.msgapi.setTitle('My App');
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Result object returned when the window closes
|
|
25
|
+
*/
|
|
26
|
+
export interface MsgResult {
|
|
27
|
+
/** Button that was clicked */
|
|
28
|
+
button: string;
|
|
29
|
+
/** Optional input field value */
|
|
30
|
+
value?: string;
|
|
31
|
+
/** Optional form data */
|
|
32
|
+
form?: Record<string, any>;
|
|
33
|
+
/** True if window was closed via close button */
|
|
34
|
+
closed?: boolean;
|
|
35
|
+
/** True if window was dismissed via Escape key */
|
|
36
|
+
dismissed?: boolean;
|
|
37
|
+
/** True if window was closed due to timeout */
|
|
38
|
+
timeout?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* File information returned by file system operations
|
|
42
|
+
*/
|
|
43
|
+
export interface FileInfo {
|
|
44
|
+
/** File name */
|
|
45
|
+
name: string;
|
|
46
|
+
/** Full file path */
|
|
47
|
+
path: string;
|
|
48
|
+
/** True if this is a directory */
|
|
49
|
+
isDir: boolean;
|
|
50
|
+
/** File size in bytes (0 for directories) */
|
|
51
|
+
size: number;
|
|
52
|
+
/** Last modified timestamp (ISO 8601 string) */
|
|
53
|
+
modified?: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Options for file selection dialogs
|
|
57
|
+
*/
|
|
58
|
+
export interface FileDialogOptions {
|
|
59
|
+
/** Dialog title */
|
|
60
|
+
title?: string;
|
|
61
|
+
/** Default filename for save dialogs */
|
|
62
|
+
defaultFilename?: string;
|
|
63
|
+
/** File filters (e.g., [{name: "Text", extensions: ["txt", "md"]}]) */
|
|
64
|
+
filters?: Array<{
|
|
65
|
+
name: string;
|
|
66
|
+
extensions: string[];
|
|
67
|
+
}>;
|
|
68
|
+
/** Default directory to open */
|
|
69
|
+
defaultPath?: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Selected file with content
|
|
73
|
+
*/
|
|
74
|
+
export interface SelectedFile {
|
|
75
|
+
/** File name */
|
|
76
|
+
name: string;
|
|
77
|
+
/** Full file path */
|
|
78
|
+
path: string;
|
|
79
|
+
/** File content as string */
|
|
80
|
+
content: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* msgapi JavaScript API
|
|
84
|
+
*
|
|
85
|
+
* Available when running inside msgview/msger via window.msgapi
|
|
86
|
+
*/
|
|
87
|
+
export interface MsgAPI {
|
|
88
|
+
/**
|
|
89
|
+
* Toggle fullscreen mode on/off
|
|
90
|
+
* @example
|
|
91
|
+
* msgapi.toggleFullscreen();
|
|
92
|
+
*/
|
|
93
|
+
toggleFullscreen(): void;
|
|
94
|
+
/**
|
|
95
|
+
* Set fullscreen mode
|
|
96
|
+
* @param enabled - true to enter fullscreen, false to exit
|
|
97
|
+
* @example
|
|
98
|
+
* msgapi.setFullscreen(true);
|
|
99
|
+
*/
|
|
100
|
+
setFullscreen(enabled: boolean): void;
|
|
101
|
+
/**
|
|
102
|
+
* Minimize the window
|
|
103
|
+
* @example
|
|
104
|
+
* msgapi.minimize();
|
|
105
|
+
*/
|
|
106
|
+
minimize(): void;
|
|
107
|
+
/**
|
|
108
|
+
* Toggle maximize/restore window
|
|
109
|
+
* @example
|
|
110
|
+
* msgapi.maximize();
|
|
111
|
+
*/
|
|
112
|
+
maximize(): void;
|
|
113
|
+
/**
|
|
114
|
+
* Set window size
|
|
115
|
+
* @param width - Window width in pixels
|
|
116
|
+
* @param height - Window height in pixels
|
|
117
|
+
* @example
|
|
118
|
+
* msgapi.setSize(800, 600);
|
|
119
|
+
*/
|
|
120
|
+
setSize(width: number, height: number): void;
|
|
121
|
+
/**
|
|
122
|
+
* Set window position
|
|
123
|
+
* @param x - X coordinate in pixels
|
|
124
|
+
* @param y - Y coordinate in pixels
|
|
125
|
+
* @example
|
|
126
|
+
* msgapi.setPosition(100, 100);
|
|
127
|
+
*/
|
|
128
|
+
setPosition(x: number, y: number): void;
|
|
129
|
+
/**
|
|
130
|
+
* Set always-on-top behavior
|
|
131
|
+
* @param enabled - true to keep window on top
|
|
132
|
+
* @example
|
|
133
|
+
* msgapi.setAlwaysOnTop(true);
|
|
134
|
+
*/
|
|
135
|
+
setAlwaysOnTop(enabled: boolean): void;
|
|
136
|
+
/**
|
|
137
|
+
* Set window title
|
|
138
|
+
* @param title - New window title
|
|
139
|
+
* @example
|
|
140
|
+
* msgapi.setTitle("My Application");
|
|
141
|
+
*/
|
|
142
|
+
setTitle(title: string): void;
|
|
143
|
+
/**
|
|
144
|
+
* Close the window
|
|
145
|
+
* @param result - Optional result to return to parent process
|
|
146
|
+
* @example
|
|
147
|
+
* // Close with default dismissed result
|
|
148
|
+
* msgapi.close();
|
|
149
|
+
*
|
|
150
|
+
* // Close with custom result
|
|
151
|
+
* msgapi.close({button: 'OK', value: 'user data'});
|
|
152
|
+
*/
|
|
153
|
+
close(result?: Partial<MsgResult>): void;
|
|
154
|
+
/**
|
|
155
|
+
* Send result and close window (legacy compatibility)
|
|
156
|
+
* @param result - Result to return to parent process
|
|
157
|
+
* @example
|
|
158
|
+
* msgapi.sendResult({button: 'Submit', value: 'form data'});
|
|
159
|
+
*/
|
|
160
|
+
sendResult(result: Partial<MsgResult>): void;
|
|
161
|
+
/**
|
|
162
|
+
* Save data to persistent storage
|
|
163
|
+
* Data is stored with 'msgapi_' prefix in localStorage
|
|
164
|
+
* @param key - Storage key
|
|
165
|
+
* @param value - Value to store (will be JSON.stringify'd)
|
|
166
|
+
* @returns true on success, false on failure
|
|
167
|
+
* @example
|
|
168
|
+
* msgapi.saveData('userPrefs', {theme: 'dark', fontSize: 14});
|
|
169
|
+
*/
|
|
170
|
+
saveData(key: string, value: any): boolean;
|
|
171
|
+
/**
|
|
172
|
+
* Load data from persistent storage
|
|
173
|
+
* @param key - Storage key
|
|
174
|
+
* @param defaultValue - Default value if key not found
|
|
175
|
+
* @returns Stored value or defaultValue
|
|
176
|
+
* @example
|
|
177
|
+
* const prefs = msgapi.loadData('userPrefs', {theme: 'light'});
|
|
178
|
+
*/
|
|
179
|
+
loadData<T = any>(key: string, defaultValue?: T): T;
|
|
180
|
+
/**
|
|
181
|
+
* Remove data from persistent storage
|
|
182
|
+
* @param key - Storage key to remove
|
|
183
|
+
* @returns true on success, false on failure
|
|
184
|
+
* @example
|
|
185
|
+
* msgapi.removeData('tempData');
|
|
186
|
+
*/
|
|
187
|
+
removeData(key: string): boolean;
|
|
188
|
+
/**
|
|
189
|
+
* Clear all msgapi data from persistent storage
|
|
190
|
+
* Only removes items with 'msgapi_' prefix
|
|
191
|
+
* @returns true on success, false on failure
|
|
192
|
+
* @example
|
|
193
|
+
* msgapi.clearData();
|
|
194
|
+
*/
|
|
195
|
+
clearData(): boolean;
|
|
196
|
+
/**
|
|
197
|
+
* File system operations namespace
|
|
198
|
+
*/
|
|
199
|
+
fs?: {
|
|
200
|
+
/**
|
|
201
|
+
* Select a file using native file picker
|
|
202
|
+
* @param options - File dialog options
|
|
203
|
+
* @returns Selected file with content, or null if cancelled
|
|
204
|
+
* @example
|
|
205
|
+
* const file = await msgapi.fs.selectFile({
|
|
206
|
+
* title: 'Open File',
|
|
207
|
+
* filters: [{name: 'Text', extensions: ['txt', 'md']}]
|
|
208
|
+
* });
|
|
209
|
+
* if (file) {
|
|
210
|
+
* console.log(file.content);
|
|
211
|
+
* }
|
|
212
|
+
*/
|
|
213
|
+
selectFile(options?: FileDialogOptions): Promise<SelectedFile | null>;
|
|
214
|
+
/**
|
|
215
|
+
* Select multiple files using native file picker
|
|
216
|
+
* @param options - File dialog options
|
|
217
|
+
* @returns Array of selected files with content
|
|
218
|
+
* @example
|
|
219
|
+
* const files = await msgapi.fs.selectFiles({
|
|
220
|
+
* title: 'Open Files'
|
|
221
|
+
* });
|
|
222
|
+
*/
|
|
223
|
+
selectFiles(options?: FileDialogOptions): Promise<SelectedFile[]>;
|
|
224
|
+
/**
|
|
225
|
+
* Save file using native save dialog
|
|
226
|
+
* @param content - File content to save
|
|
227
|
+
* @param defaultFilename - Default filename
|
|
228
|
+
* @param options - Additional dialog options
|
|
229
|
+
* @returns Path where file was saved, or null if cancelled
|
|
230
|
+
* @example
|
|
231
|
+
* const path = await msgapi.fs.saveFileAs('Hello World', 'greeting.txt');
|
|
232
|
+
*/
|
|
233
|
+
saveFileAs(content: string, defaultFilename?: string, options?: FileDialogOptions): Promise<string | null>;
|
|
234
|
+
/**
|
|
235
|
+
* Select a directory using native folder picker
|
|
236
|
+
* @param options - Dialog options
|
|
237
|
+
* @returns Selected directory path, or null if cancelled
|
|
238
|
+
* @example
|
|
239
|
+
* const dir = await msgapi.fs.selectFolder({
|
|
240
|
+
* title: 'Select Output Folder'
|
|
241
|
+
* });
|
|
242
|
+
*/
|
|
243
|
+
selectFolder(options?: FileDialogOptions): Promise<string | null>;
|
|
244
|
+
/**
|
|
245
|
+
* Read file contents
|
|
246
|
+
* Note: Requires allowFs: true flag when launching msgview/msger
|
|
247
|
+
* @param path - File path to read
|
|
248
|
+
* @returns File content as string
|
|
249
|
+
* @example
|
|
250
|
+
* const content = await msgapi.fs.read('/path/to/file.txt');
|
|
251
|
+
*/
|
|
252
|
+
read(path: string): Promise<string>;
|
|
253
|
+
/**
|
|
254
|
+
* Write file contents
|
|
255
|
+
* Note: Requires allowFs: true flag when launching msgview/msger
|
|
256
|
+
* @param path - File path to write
|
|
257
|
+
* @param content - Content to write
|
|
258
|
+
* @example
|
|
259
|
+
* await msgapi.fs.write('/path/to/file.txt', 'Hello World');
|
|
260
|
+
*/
|
|
261
|
+
write(path: string, content: string): Promise<void>;
|
|
262
|
+
/**
|
|
263
|
+
* List directory contents
|
|
264
|
+
* Note: Requires allowFs: true flag when launching msgview/msger
|
|
265
|
+
* @param path - Directory path to list
|
|
266
|
+
* @returns Array of file information
|
|
267
|
+
* @example
|
|
268
|
+
* const files = await msgapi.fs.list('/path/to/dir');
|
|
269
|
+
*/
|
|
270
|
+
list(path: string): Promise<FileInfo[]>;
|
|
271
|
+
/**
|
|
272
|
+
* Check if file or directory exists
|
|
273
|
+
* Note: Requires allowFs: true flag when launching msgview/msger
|
|
274
|
+
* @param path - Path to check
|
|
275
|
+
* @returns true if exists
|
|
276
|
+
* @example
|
|
277
|
+
* const exists = await msgapi.fs.exists('/path/to/file.txt');
|
|
278
|
+
*/
|
|
279
|
+
exists(path: string): Promise<boolean>;
|
|
280
|
+
/**
|
|
281
|
+
* Delete file or directory
|
|
282
|
+
* Note: Requires allowFs: true flag when launching msgview/msger
|
|
283
|
+
* @param path - Path to delete
|
|
284
|
+
* @example
|
|
285
|
+
* await msgapi.fs.delete('/path/to/file.txt');
|
|
286
|
+
*/
|
|
287
|
+
delete(path: string): Promise<void>;
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Helper to check if code is running in msgview/msger
|
|
292
|
+
* @returns true if running in msgapi environment
|
|
293
|
+
* @example
|
|
294
|
+
* if (isMsgAPI()) {
|
|
295
|
+
* msgapi.setTitle('Running in msgview/msger!');
|
|
296
|
+
* } else {
|
|
297
|
+
* console.log('Running in browser');
|
|
298
|
+
* }
|
|
299
|
+
*/
|
|
300
|
+
export declare function isMsgAPI(): boolean;
|
|
301
|
+
/**
|
|
302
|
+
* Get msgapi API with fallback for browser compatibility
|
|
303
|
+
* @returns msgapi API if available, or stub implementation for browser
|
|
304
|
+
* @example
|
|
305
|
+
* const api = getMsgAPI();
|
|
306
|
+
* api.saveData('key', 'value'); // Works in both msgview/msger and browser
|
|
307
|
+
*/
|
|
308
|
+
export declare function getMsgAPI(): MsgAPI;
|
|
309
|
+
/**
|
|
310
|
+
* Declare global window.msgapi
|
|
311
|
+
*/
|
|
312
|
+
declare global {
|
|
313
|
+
interface Window {
|
|
314
|
+
msgapi?: MsgAPI;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
declare const _default: {
|
|
318
|
+
isMsgAPI: typeof isMsgAPI;
|
|
319
|
+
getMsgAPI: typeof getMsgAPI;
|
|
320
|
+
};
|
|
321
|
+
export default _default;
|
|
322
|
+
//# sourceMappingURL=msgapidefs.d.ts.map
|
package/msgapidefs.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript definitions for the msgapi JavaScript API
|
|
3
|
+
*
|
|
4
|
+
* This module provides type-safe access to msgapi's window control,
|
|
5
|
+
* data persistence, and file system features (used by msgview and msger).
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import type { MsgAPI } from '@bobfrankston/msgapidefs';
|
|
10
|
+
*
|
|
11
|
+
* declare global {
|
|
12
|
+
* interface Window {
|
|
13
|
+
* msgapi?: MsgAPI;
|
|
14
|
+
* }
|
|
15
|
+
* }
|
|
16
|
+
*
|
|
17
|
+
* // Check if running in msgview/msger
|
|
18
|
+
* if (window.msgapi) {
|
|
19
|
+
* window.msgapi.setTitle('My App');
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Helper to check if code is running in msgview/msger
|
|
25
|
+
* @returns true if running in msgapi environment
|
|
26
|
+
* @example
|
|
27
|
+
* if (isMsgAPI()) {
|
|
28
|
+
* msgapi.setTitle('Running in msgview/msger!');
|
|
29
|
+
* } else {
|
|
30
|
+
* console.log('Running in browser');
|
|
31
|
+
* }
|
|
32
|
+
*/
|
|
33
|
+
export function isMsgAPI() {
|
|
34
|
+
return typeof window !== 'undefined' && typeof window.msgapi !== 'undefined';
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get msgapi API with fallback for browser compatibility
|
|
38
|
+
* @returns msgapi API if available, or stub implementation for browser
|
|
39
|
+
* @example
|
|
40
|
+
* const api = getMsgAPI();
|
|
41
|
+
* api.saveData('key', 'value'); // Works in both msgview/msger and browser
|
|
42
|
+
*/
|
|
43
|
+
export function getMsgAPI() {
|
|
44
|
+
if (isMsgAPI()) {
|
|
45
|
+
return window.msgapi;
|
|
46
|
+
}
|
|
47
|
+
// Return browser-compatible stub
|
|
48
|
+
return {
|
|
49
|
+
// Window control - no-op in browser
|
|
50
|
+
toggleFullscreen: () => { },
|
|
51
|
+
setFullscreen: () => { },
|
|
52
|
+
minimize: () => { },
|
|
53
|
+
maximize: () => { },
|
|
54
|
+
setSize: () => { },
|
|
55
|
+
setPosition: () => { },
|
|
56
|
+
setAlwaysOnTop: () => { },
|
|
57
|
+
setTitle: (title) => { document.title = title; },
|
|
58
|
+
close: () => { window.close(); },
|
|
59
|
+
sendResult: () => { window.close(); },
|
|
60
|
+
// Data persistence - use localStorage in browser
|
|
61
|
+
saveData: (key, value) => {
|
|
62
|
+
try {
|
|
63
|
+
localStorage.setItem('msgapi_' + key, JSON.stringify(value));
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
loadData: (key, defaultValue) => {
|
|
71
|
+
try {
|
|
72
|
+
const item = localStorage.getItem('msgapi_' + key);
|
|
73
|
+
return item ? JSON.parse(item) : defaultValue;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return defaultValue;
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
removeData: (key) => {
|
|
80
|
+
try {
|
|
81
|
+
localStorage.removeItem('msgapi_' + key);
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
clearData: () => {
|
|
89
|
+
try {
|
|
90
|
+
const keys = Object.keys(localStorage);
|
|
91
|
+
for (const key of keys) {
|
|
92
|
+
if (key.startsWith('msgapi_')) {
|
|
93
|
+
localStorage.removeItem(key);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
// File system - not available in browser
|
|
103
|
+
fs: undefined
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
export default {
|
|
107
|
+
isMsgAPI,
|
|
108
|
+
getMsgAPI
|
|
109
|
+
};
|
|
110
|
+
//# sourceMappingURL=msgapidefs.js.map
|