@bobfrankston/msger 0.1.73 → 0.1.75
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/KNOWN-BUGS.md +121 -0
- package/MSGER-API-SUMMARY.md +162 -0
- package/MSGER-API.md +376 -0
- package/README.md +93 -0
- package/SESSION-2025-11-06.md +191 -0
- package/SESSION-NOTES.md +678 -0
- package/clihandler.d.ts.map +1 -1
- package/clihandler.js +62 -2
- package/clihandler.js.map +1 -1
- package/clihandler.ts +60 -2
- package/icon.png +0 -0
- package/icon1.png +0 -0
- package/msger-native/Cargo.toml +1 -0
- package/msger-native/bin/msgernative.exe +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Breadcrumbs +12 -118
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/BrowserMetrics/{BrowserMetrics-690552AF-DCD4.pma → BrowserMetrics-690B9AD3-657C.pma} +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/BrowserMetrics/{BrowserMetrics-69055373-F88C.pma → BrowserMetrics-690BA05A-501C.pma} +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Crashpad/settings.dat +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/BrowsingTopicsState +1 -1
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/data_0 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/data_1 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/{BrowserMetrics/BrowserMetrics-69055587-A65C.pma → Default/Cache/Cache_Data/data_2} +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/data_3 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/f_000001 +383 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/f_000002 +1091 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/f_000003 +2153 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/f_000004 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/f_000005 +626 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/f_000006 +393 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Cache/Cache_Data/index +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/01241693cfdc32b9_0 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/0ba1eea781f3552c_0 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/323aa210eebefe2c_0 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/4608446ac118e77a_0 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/6938205dc2f77841_0 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/6de12299dc89e5f3_0 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/8f403c112eaa455b_0 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/9a3aceb491137f07_0 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/aedb266cbaf9c28f_0 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/ca526fdda86d0b9d_0 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/f5d11d783c9fdf69_0 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Code Cache/js/index-dir/the-real-index +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Collections/collectionsSQLite +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Collections/collectionsSQLite-journal +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/DIPS +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/DawnGraphiteCache/data_1 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/DawnGraphiteCache/index +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/DawnWebGPUCache/data_1 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/DawnWebGPUCache/index +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Extension State/LOG +3 -3
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Extension State/LOG.old +3 -3
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Favicons +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/GPUCache/data_0 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/GPUCache/data_1 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/GPUCache/data_2 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/GPUCache/index +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/History +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Local Storage/leveldb/000003.log +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Local Storage/leveldb/LOG +3 -3
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Local Storage/leveldb/LOG.old +3 -3
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/MediaDeviceSalts +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/MediaDeviceSalts-journal +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Network/Network Persistent State +1 -1
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Network/TransportSecurity +1 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Preferences +1 -1
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/CacheStorage/14e849fa8522d406112ea607cf7fd6342b71b987/249ee9af-c3df-4a86-89a8-2c51f3370ee0/index +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/CacheStorage/14e849fa8522d406112ea607cf7fd6342b71b987/249ee9af-c3df-4a86-89a8-2c51f3370ee0/index-dir/the-real-index +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/CacheStorage/14e849fa8522d406112ea607cf7fd6342b71b987/index.txt +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/Database/000003.log +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/Database/CURRENT +1 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/Database/LOCK +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/Database/LOG +3 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/Database/LOG.old +3 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/Database/MANIFEST-000001 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/ScriptCache/2cc80dabc69f58b6_0 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/ScriptCache/2cc80dabc69f58b6_1 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/ScriptCache/index +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Service Worker/ScriptCache/index-dir/the-real-index +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Session Storage/000003.log +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Session Storage/LOG +3 -3
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Session Storage/LOG.old +3 -3
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Site Characteristics Database/000003.log +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Site Characteristics Database/LOG +3 -3
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Site Characteristics Database/LOG.old +3 -3
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Sync Data/LevelDB/LOG +3 -3
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/Sync Data/LevelDB/LOG.old +3 -3
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/WebStorage/QuotaManager +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/WebStorage/QuotaManager-journal +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/favorites_diagnostic.log +27 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/shared_proto_db/000003.log +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/shared_proto_db/LOG +3 -3
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/shared_proto_db/LOG.old +3 -3
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/shared_proto_db/metadata/000003.log +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/shared_proto_db/metadata/LOG +3 -3
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Default/shared_proto_db/metadata/LOG.old +3 -3
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/GrShaderCache/data_0 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/GrShaderCache/data_1 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/GrShaderCache/data_3 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/GrShaderCache/f_000003 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/GrShaderCache/f_000004 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/GrShaderCache/index +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/GraphiteDawnCache/data_1 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/GraphiteDawnCache/index +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/Local State +1 -1
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/RevisitationBloomfilter +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/ShaderCache/data_1 +0 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/ShaderCache/index +0 -0
- package/msger-native/src/main.rs +343 -37
- package/msger-native/src/template.html +103 -28
- package/msger-storage-demo.html +290 -0
- package/msger.code-workspace +3 -0
- package/msgerdefs/README.md +122 -0
- package/msgerdefs/msgerdefs.d.ts +322 -0
- package/msgerdefs/msgerdefs.d.ts.map +1 -0
- package/msgerdefs/msgerdefs.js +110 -0
- package/msgerdefs/msgerdefs.js.map +1 -0
- package/msgerdefs/msgerdefs.ts +427 -0
- package/msgerdefs/package.json +38 -0
- package/msgerdefs/samples.html +431 -0
- package/msgerdefs/test1.cmd +1 -0
- package/msgerdefs/tsconfig.json +17 -0
- package/msgernative-linux-x64 +0 -0
- package/package.json +5 -1
- package/shower.d.ts +2 -0
- package/shower.d.ts.map +1 -1
- package/shower.js +17 -0
- package/shower.js.map +1 -1
- package/shower.ts +24 -0
- package/test-data-persistence.html +315 -0
- package/test-htmlfrom.html +29 -0
- package/test-ipc-reach.html +113 -0
- package/test-msger-api.html +120 -0
- package/test-msger-functions.html +325 -0
- package/msger-native/bin/msgernative.exe.WebView2/EBWebView/BrowserMetrics/BrowserMetrics-69055419-C8A0.pma +0 -0
|
@@ -72,6 +72,39 @@
|
|
|
72
72
|
</div>
|
|
73
73
|
<div id="countdown" style="position: fixed; top: 5px; right: 5px; background: rgba(255, 255, 0, 0.3); padding: 5px 10px; font-size: 14px; font-weight: bold; border-radius: 4px; display: none;"></div>
|
|
74
74
|
<script>
|
|
75
|
+
// msger JavaScript API with error handling
|
|
76
|
+
(function() {
|
|
77
|
+
// Check if IPC is available
|
|
78
|
+
const hasIPC = typeof window.ipc !== 'undefined' && window.ipc.postMessage;
|
|
79
|
+
|
|
80
|
+
// Helper to safely send IPC messages
|
|
81
|
+
function safePostMessage(data) {
|
|
82
|
+
try {
|
|
83
|
+
if (!hasIPC) {
|
|
84
|
+
console.error('msger API: window.ipc not available');
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
window.ipc.postMessage(JSON.stringify(data));
|
|
88
|
+
return true;
|
|
89
|
+
} catch(e) {
|
|
90
|
+
console.error('msger API error:', e);
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
window.msger = {
|
|
96
|
+
// Check if running in msger environment
|
|
97
|
+
isAvailable: function() {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// NOTE: Use native browser APIs instead of msger wrappers:
|
|
103
|
+
// - localStorage (native)
|
|
104
|
+
// - window.close() (native)
|
|
105
|
+
// msger API is minimal by design - we're just a CLI window wrapper
|
|
106
|
+
})();
|
|
107
|
+
|
|
75
108
|
// Countdown timer overlay
|
|
76
109
|
try {
|
|
77
110
|
const timeoutSeconds = {TIMEOUT_SECONDS};
|
|
@@ -104,30 +137,53 @@
|
|
|
104
137
|
}
|
|
105
138
|
|
|
106
139
|
function sendResult(button) {
|
|
107
|
-
|
|
140
|
+
console.log('Button clicked:', button);
|
|
108
141
|
|
|
109
|
-
//
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
result.value = inputField.value;
|
|
113
|
-
}
|
|
142
|
+
// Try IPC first - maybe it works in template mode?
|
|
143
|
+
try {
|
|
144
|
+
const result = { button: button };
|
|
114
145
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
forms.forEach(form => {
|
|
120
|
-
const data = new FormData(form);
|
|
121
|
-
data.forEach((value, key) => {
|
|
122
|
-
formData[key] = value;
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
if (Object.keys(formData).length > 0) {
|
|
126
|
-
result.form = formData;
|
|
146
|
+
// Get input field value if present
|
|
147
|
+
const inputField = document.getElementById('inputField');
|
|
148
|
+
if (inputField) {
|
|
149
|
+
result.value = inputField.value;
|
|
127
150
|
}
|
|
151
|
+
|
|
152
|
+
if (typeof window.ipc !== 'undefined' && window.ipc.postMessage) {
|
|
153
|
+
console.log('Attempting IPC postMessage with:', result);
|
|
154
|
+
window.ipc.postMessage(JSON.stringify(result));
|
|
155
|
+
console.log('IPC postMessage succeeded!');
|
|
156
|
+
return true;
|
|
157
|
+
} else {
|
|
158
|
+
console.error('window.ipc not available');
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
} catch(e) {
|
|
162
|
+
console.error('IPC failed:', e);
|
|
163
|
+
return false;
|
|
128
164
|
}
|
|
129
165
|
|
|
130
|
-
|
|
166
|
+
// const result = { button: button };
|
|
167
|
+
// // Get input field value if present
|
|
168
|
+
// const inputField = document.getElementById('inputField');
|
|
169
|
+
// if (inputField) {
|
|
170
|
+
// result.value = inputField.value;
|
|
171
|
+
// }
|
|
172
|
+
// // Get all form data if forms are present
|
|
173
|
+
// const forms = document.querySelectorAll('form');
|
|
174
|
+
// if (forms.length > 0) {
|
|
175
|
+
// const formData = {};
|
|
176
|
+
// forms.forEach(form => {
|
|
177
|
+
// const data = new FormData(form);
|
|
178
|
+
// data.forEach((value, key) => {
|
|
179
|
+
// formData[key] = value;
|
|
180
|
+
// });
|
|
181
|
+
// });
|
|
182
|
+
// if (Object.keys(formData).length > 0) {
|
|
183
|
+
// result.form = formData;
|
|
184
|
+
// }
|
|
185
|
+
// }
|
|
186
|
+
// window.ipc.postMessage(JSON.stringify(result));
|
|
131
187
|
}
|
|
132
188
|
|
|
133
189
|
// Auto-size window to content
|
|
@@ -168,15 +224,15 @@
|
|
|
168
224
|
});
|
|
169
225
|
}
|
|
170
226
|
|
|
227
|
+
// Zoom support with mouse wheel
|
|
228
|
+
let zoomLevel = 1.0;
|
|
229
|
+
|
|
171
230
|
// Set initial zoom level if specified
|
|
172
231
|
const initialZoom = {ZOOM_PERCENT};
|
|
173
232
|
if (initialZoom) {
|
|
174
233
|
zoomLevel = initialZoom / 100.0;
|
|
175
234
|
document.body.style.zoom = zoomLevel;
|
|
176
235
|
}
|
|
177
|
-
|
|
178
|
-
// Zoom support with mouse wheel
|
|
179
|
-
let zoomLevel = 1.0;
|
|
180
236
|
document.addEventListener('wheel', function(e) {
|
|
181
237
|
// Only zoom when Ctrl is held (or Cmd on Mac)
|
|
182
238
|
if (e.ctrlKey || e.metaKey) {
|
|
@@ -197,17 +253,30 @@
|
|
|
197
253
|
window.addEventListener('load', function() {
|
|
198
254
|
document.body.focus();
|
|
199
255
|
});
|
|
200
|
-
|
|
256
|
+
|
|
201
257
|
// Also focus when window gets focus
|
|
202
258
|
window.addEventListener('focus', function() {
|
|
203
259
|
document.body.focus();
|
|
204
260
|
});
|
|
205
|
-
|
|
261
|
+
|
|
206
262
|
// And try again after a short delay
|
|
207
263
|
setTimeout(() => {
|
|
208
264
|
document.body.focus();
|
|
209
265
|
}, 100);
|
|
210
266
|
|
|
267
|
+
// Auto-trigger fullscreen if requested
|
|
268
|
+
const startFullscreen = {FULLSCREEN};
|
|
269
|
+
if (startFullscreen) {
|
|
270
|
+
window.addEventListener('load', function() {
|
|
271
|
+
// Wait a bit for the window to be ready
|
|
272
|
+
setTimeout(() => {
|
|
273
|
+
document.documentElement.requestFullscreen().catch(err => {
|
|
274
|
+
console.error('Failed to enter fullscreen:', err);
|
|
275
|
+
});
|
|
276
|
+
}, 100);
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
|
|
211
280
|
document.addEventListener('keydown', function(e) {
|
|
212
281
|
if (e.key === 'Escape') {
|
|
213
282
|
e.preventDefault();
|
|
@@ -215,14 +284,20 @@
|
|
|
215
284
|
if (document.fullscreenElement) {
|
|
216
285
|
document.exitFullscreen();
|
|
217
286
|
} else {
|
|
218
|
-
|
|
219
|
-
window
|
|
287
|
+
// CANNOT use IPC - it crashes!
|
|
288
|
+
// The Rust window handler should catch Esc key
|
|
289
|
+
console.error('Esc key: Cannot send via IPC (crashes). Close window with X button instead.');
|
|
290
|
+
// const result = { button: 'Cancel', dismissed: true };
|
|
291
|
+
// window.ipc.postMessage(JSON.stringify(result));
|
|
220
292
|
}
|
|
221
293
|
} else if (e.key === 'F11') {
|
|
222
|
-
//
|
|
294
|
+
// Note: This uses HTML5 fullscreen, not native window fullscreen
|
|
295
|
+
// The Rust window handler should catch F11 for native fullscreen
|
|
223
296
|
e.preventDefault();
|
|
224
297
|
if (!document.fullscreenElement) {
|
|
225
|
-
document.documentElement.requestFullscreen()
|
|
298
|
+
document.documentElement.requestFullscreen().catch(err => {
|
|
299
|
+
console.warn('HTML5 fullscreen failed:', err);
|
|
300
|
+
});
|
|
226
301
|
} else {
|
|
227
302
|
document.exitFullscreen();
|
|
228
303
|
}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>msger Storage API Demo</title>
|
|
6
|
+
<style>
|
|
7
|
+
body {
|
|
8
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
9
|
+
padding: 30px;
|
|
10
|
+
max-width: 800px;
|
|
11
|
+
margin: 0 auto;
|
|
12
|
+
background: #f5f5f5;
|
|
13
|
+
}
|
|
14
|
+
h1 { color: #333; }
|
|
15
|
+
.info {
|
|
16
|
+
background: #e3f2fd;
|
|
17
|
+
border-left: 4px solid #0066cc;
|
|
18
|
+
padding: 15px;
|
|
19
|
+
margin: 20px 0;
|
|
20
|
+
border-radius: 4px;
|
|
21
|
+
}
|
|
22
|
+
.warning {
|
|
23
|
+
background: #fff3cd;
|
|
24
|
+
border-left: 4px solid #ffc107;
|
|
25
|
+
padding: 15px;
|
|
26
|
+
margin: 20px 0;
|
|
27
|
+
border-radius: 4px;
|
|
28
|
+
}
|
|
29
|
+
.section {
|
|
30
|
+
background: white;
|
|
31
|
+
padding: 20px;
|
|
32
|
+
margin: 20px 0;
|
|
33
|
+
border-radius: 8px;
|
|
34
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
35
|
+
}
|
|
36
|
+
input, textarea {
|
|
37
|
+
width: 100%;
|
|
38
|
+
padding: 10px;
|
|
39
|
+
margin: 5px 0;
|
|
40
|
+
border: 1px solid #ddd;
|
|
41
|
+
border-radius: 4px;
|
|
42
|
+
font-family: inherit;
|
|
43
|
+
box-sizing: border-box;
|
|
44
|
+
}
|
|
45
|
+
button {
|
|
46
|
+
padding: 10px 20px;
|
|
47
|
+
margin: 5px;
|
|
48
|
+
background: #0066cc;
|
|
49
|
+
color: white;
|
|
50
|
+
border: none;
|
|
51
|
+
border-radius: 4px;
|
|
52
|
+
cursor: pointer;
|
|
53
|
+
font-size: 14px;
|
|
54
|
+
}
|
|
55
|
+
button:hover { background: #0052a3; }
|
|
56
|
+
button.secondary { background: #6c757d; }
|
|
57
|
+
button.secondary:hover { background: #5a6268; }
|
|
58
|
+
.output {
|
|
59
|
+
background: #f8f9fa;
|
|
60
|
+
border: 1px solid #dee2e6;
|
|
61
|
+
border-radius: 4px;
|
|
62
|
+
padding: 15px;
|
|
63
|
+
margin: 10px 0;
|
|
64
|
+
font-family: 'Courier New', monospace;
|
|
65
|
+
font-size: 13px;
|
|
66
|
+
white-space: pre-wrap;
|
|
67
|
+
min-height: 60px;
|
|
68
|
+
}
|
|
69
|
+
code {
|
|
70
|
+
background: #f4f4f4;
|
|
71
|
+
padding: 2px 6px;
|
|
72
|
+
border-radius: 3px;
|
|
73
|
+
font-family: 'Courier New', monospace;
|
|
74
|
+
}
|
|
75
|
+
</style>
|
|
76
|
+
</head>
|
|
77
|
+
<body>
|
|
78
|
+
<h1>msger Storage API Demo</h1>
|
|
79
|
+
|
|
80
|
+
<div class="info">
|
|
81
|
+
<strong>✅ What Works:</strong> localStorage-based persistence API<br>
|
|
82
|
+
<strong>❌ What's Broken:</strong> All window controls, buttons, F11 (IPC crashes)<br>
|
|
83
|
+
<strong>🔧 How to Close:</strong> Click the X button (top-right corner)
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<div class="warning">
|
|
87
|
+
<strong>⚠️ Window Controls Disabled</strong><br>
|
|
88
|
+
Due to a wry library bug, all window operations via JavaScript crash the app.
|
|
89
|
+
Configure window at startup using CLI flags: <code>-size 800,600 -title "My App"</code>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
<!-- Basic Storage -->
|
|
93
|
+
<div class="section">
|
|
94
|
+
<h2>Basic Storage (with Timestamps)</h2>
|
|
95
|
+
<input type="text" id="key" value="myData" placeholder="Storage key">
|
|
96
|
+
<textarea id="value" rows="3" placeholder="Enter any text...">Hello from msger!</textarea>
|
|
97
|
+
<div>
|
|
98
|
+
<button onclick="saveData()">Save Data</button>
|
|
99
|
+
<button onclick="loadData()">Load Data</button>
|
|
100
|
+
<button onclick="removeData()" class="secondary">Remove Data</button>
|
|
101
|
+
</div>
|
|
102
|
+
<div id="output1" class="output">Click Save to store data</div>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
<!-- Complex Data -->
|
|
106
|
+
<div class="section">
|
|
107
|
+
<h2>Structured Data</h2>
|
|
108
|
+
<p>Save complex objects, arrays, and nested data</p>
|
|
109
|
+
<button onclick="saveUserSettings()">Save User Settings</button>
|
|
110
|
+
<button onclick="loadUserSettings()">Load User Settings</button>
|
|
111
|
+
<div id="output2" class="output">Click to save/load structured data</div>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<!-- List All Data -->
|
|
115
|
+
<div class="section">
|
|
116
|
+
<h2>Manage Storage</h2>
|
|
117
|
+
<button onclick="listAll()">List All Saved Data</button>
|
|
118
|
+
<button onclick="clearAll()" class="secondary">Clear All msger Data</button>
|
|
119
|
+
<div id="output3" class="output">Click to list or clear data</div>
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<!-- File-Like Storage -->
|
|
123
|
+
<div class="section">
|
|
124
|
+
<h2>Virtual File Storage</h2>
|
|
125
|
+
<p>Store "files" in localStorage and export them</p>
|
|
126
|
+
<input type="text" id="filename" value="document.txt" placeholder="Filename">
|
|
127
|
+
<textarea id="filecontent" rows="5" placeholder="File content...">This is a virtual file stored in localStorage.</textarea>
|
|
128
|
+
<div>
|
|
129
|
+
<button onclick="saveFile()">Save Virtual File</button>
|
|
130
|
+
<button onclick="loadFile()">Load Virtual File</button>
|
|
131
|
+
<button onclick="downloadFile()">Export (Download)</button>
|
|
132
|
+
</div>
|
|
133
|
+
<div id="output4" class="output">Click to save/load/export files</div>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
<script>
|
|
137
|
+
// Check if msger API is available
|
|
138
|
+
const hasMsger = typeof window.msger !== 'undefined';
|
|
139
|
+
if (!hasMsger) {
|
|
140
|
+
alert('WARNING: msger API not found! Are you running in msger?');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function log(id, msg, color = '#4ec9b0') {
|
|
144
|
+
document.getElementById(id).textContent = msg;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Basic Storage
|
|
148
|
+
function saveData() {
|
|
149
|
+
const key = document.getElementById('key').value;
|
|
150
|
+
const value = document.getElementById('value').value;
|
|
151
|
+
const data = {
|
|
152
|
+
value: value,
|
|
153
|
+
savedAt: new Date().toISOString(),
|
|
154
|
+
savedTimestamp: Date.now()
|
|
155
|
+
};
|
|
156
|
+
const result = msger.saveData(key, data);
|
|
157
|
+
log('output1', `✅ Saved!\nKey: ${key}\nValue: ${value}\nTime: ${data.savedAt}\n\nData persists across restarts!`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function loadData() {
|
|
161
|
+
const key = document.getElementById('key').value;
|
|
162
|
+
const data = msger.loadData(key, null);
|
|
163
|
+
if (data) {
|
|
164
|
+
const age = Math.floor((Date.now() - data.savedTimestamp) / 1000);
|
|
165
|
+
log('output1', `✅ Loaded!\nKey: ${key}\nValue: ${data.value}\nSaved: ${data.savedAt}\nAge: ${age} seconds ago\n\nThis proves persistence works!`);
|
|
166
|
+
document.getElementById('value').value = data.value;
|
|
167
|
+
} else {
|
|
168
|
+
log('output1', `❌ Key "${key}" not found`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function removeData() {
|
|
173
|
+
const key = document.getElementById('key').value;
|
|
174
|
+
msger.removeData(key);
|
|
175
|
+
log('output1', `✅ Removed key: ${key}`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Structured Data
|
|
179
|
+
function saveUserSettings() {
|
|
180
|
+
const settings = {
|
|
181
|
+
theme: 'dark',
|
|
182
|
+
fontSize: 14,
|
|
183
|
+
language: 'en',
|
|
184
|
+
notifications: {
|
|
185
|
+
email: true,
|
|
186
|
+
push: false
|
|
187
|
+
},
|
|
188
|
+
recentFiles: [
|
|
189
|
+
'document1.txt',
|
|
190
|
+
'notes.md',
|
|
191
|
+
'project.json'
|
|
192
|
+
]
|
|
193
|
+
};
|
|
194
|
+
msger.saveData('userSettings', settings);
|
|
195
|
+
log('output2', `✅ Saved complex object:\n${JSON.stringify(settings, null, 2)}`);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function loadUserSettings() {
|
|
199
|
+
const settings = msger.loadData('userSettings', null);
|
|
200
|
+
if (settings) {
|
|
201
|
+
log('output2', `✅ Loaded settings:\n${JSON.stringify(settings, null, 2)}`);
|
|
202
|
+
} else {
|
|
203
|
+
log('output2', `❌ No settings found. Click "Save User Settings" first.`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// List All
|
|
208
|
+
function listAll() {
|
|
209
|
+
const allKeys = Object.keys(localStorage);
|
|
210
|
+
const msgerKeys = allKeys.filter(k => k.startsWith('msger_'));
|
|
211
|
+
if (msgerKeys.length === 0) {
|
|
212
|
+
log('output3', `No msger data found. Save something first!`);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
let output = `Found ${msgerKeys.length} items:\n\n`;
|
|
216
|
+
msgerKeys.forEach(key => {
|
|
217
|
+
const displayKey = key.replace('msger_', '');
|
|
218
|
+
const data = msger.loadData(displayKey, null);
|
|
219
|
+
if (data && data.savedAt) {
|
|
220
|
+
const age = Math.floor((Date.now() - data.savedTimestamp) / 1000);
|
|
221
|
+
output += `📄 ${displayKey} (${age}s ago)\n`;
|
|
222
|
+
} else {
|
|
223
|
+
output += `📄 ${displayKey}\n`;
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
log('output3', output);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function clearAll() {
|
|
230
|
+
if (confirm('Clear all msger data?')) {
|
|
231
|
+
msger.clearData();
|
|
232
|
+
log('output3', `✅ All msger data cleared!`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Virtual Files
|
|
237
|
+
function saveFile() {
|
|
238
|
+
const filename = document.getElementById('filename').value;
|
|
239
|
+
const content = document.getElementById('filecontent').value;
|
|
240
|
+
const fileData = {
|
|
241
|
+
name: filename,
|
|
242
|
+
content: content,
|
|
243
|
+
size: content.length,
|
|
244
|
+
created: new Date().toISOString()
|
|
245
|
+
};
|
|
246
|
+
msger.saveData('file_' + filename, fileData);
|
|
247
|
+
log('output4', `✅ Saved virtual file:\nName: ${filename}\nSize: ${content.length} bytes\nCreated: ${fileData.created}`);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function loadFile() {
|
|
251
|
+
const filename = document.getElementById('filename').value;
|
|
252
|
+
const fileData = msger.loadData('file_' + filename, null);
|
|
253
|
+
if (fileData) {
|
|
254
|
+
document.getElementById('filecontent').value = fileData.content;
|
|
255
|
+
log('output4', `✅ Loaded file:\nName: ${fileData.name}\nSize: ${fileData.size} bytes\nCreated: ${fileData.created}`);
|
|
256
|
+
} else {
|
|
257
|
+
log('output4', `❌ File "${filename}" not found`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function downloadFile() {
|
|
262
|
+
const filename = document.getElementById('filename').value;
|
|
263
|
+
const fileData = msger.loadData('file_' + filename, null);
|
|
264
|
+
if (fileData) {
|
|
265
|
+
const blob = new Blob([fileData.content], { type: 'text/plain' });
|
|
266
|
+
const url = URL.createObjectURL(blob);
|
|
267
|
+
const a = document.createElement('a');
|
|
268
|
+
a.href = url;
|
|
269
|
+
a.download = fileData.name;
|
|
270
|
+
a.click();
|
|
271
|
+
URL.revokeObjectURL(url);
|
|
272
|
+
log('output4', `✅ Downloaded: ${fileData.name}`);
|
|
273
|
+
} else {
|
|
274
|
+
log('output4', `❌ File "${filename}" not found. Save it first!`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Auto-load on startup
|
|
279
|
+
window.addEventListener('load', function() {
|
|
280
|
+
// Check for persisted data
|
|
281
|
+
const testKey = document.getElementById('key').value;
|
|
282
|
+
const data = msger.loadData(testKey, null);
|
|
283
|
+
if (data) {
|
|
284
|
+
log('output1', `✅ Found persisted data! Click "Load Data" to see it.`);
|
|
285
|
+
listAll();
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
</script>
|
|
289
|
+
</body>
|
|
290
|
+
</html>
|
package/msger.code-workspace
CHANGED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# @bobfrankston/msgerdefs
|
|
2
|
+
|
|
3
|
+
TypeScript definitions for the **msger** JavaScript API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @bobfrankston/msgerdefs
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### TypeScript
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import type { MsgerAPI } from '@bobfrankston/msgerdefs';
|
|
17
|
+
import { isMsger, getMsgerAPI } from '@bobfrankston/msgerdefs';
|
|
18
|
+
|
|
19
|
+
// Option 1: Type the global window.msger
|
|
20
|
+
declare global {
|
|
21
|
+
interface Window {
|
|
22
|
+
msger?: MsgerAPI;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Check if running in msger
|
|
27
|
+
if (isMsger()) {
|
|
28
|
+
window.msger!.setTitle('My Application');
|
|
29
|
+
window.msger!.saveData('lastOpened', new Date().toISOString());
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Option 2: Use getMsgerAPI() for cross-platform compatibility
|
|
33
|
+
const msger = getMsgerAPI();
|
|
34
|
+
msger.saveData('userPrefs', { theme: 'dark' }); // Works in both msger and browser!
|
|
35
|
+
msger.setTitle('My App'); // Only works in msger, no-op in browser
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### JavaScript
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
import { isMsger, getMsgerAPI } from '@bobfrankston/msgerdefs';
|
|
42
|
+
|
|
43
|
+
const msger = getMsgerAPI();
|
|
44
|
+
|
|
45
|
+
// Data persistence (works in both msger and browser)
|
|
46
|
+
msger.saveData('userSettings', { fontSize: 14, theme: 'dark' });
|
|
47
|
+
const settings = msger.loadData('userSettings', { fontSize: 12 });
|
|
48
|
+
|
|
49
|
+
// Window control (msger only, gracefully degrades in browser)
|
|
50
|
+
if (isMsger()) {
|
|
51
|
+
msger.toggleFullscreen();
|
|
52
|
+
msger.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 msger 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 msger:**
|
|
94
|
+
```bash
|
|
95
|
+
msger -url "file:///path/to/node_modules/@bobfrankston/msgerdefs/samples.html"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Test in browser:**
|
|
99
|
+
```bash
|
|
100
|
+
# Open samples.html in your browser to test browser compatibility
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The samples demonstrate:
|
|
104
|
+
- Window control (fullscreen, minimize, maximize, resize, position)
|
|
105
|
+
- Data persistence (save/load user preferences, session data, recent files)
|
|
106
|
+
- Presentation mode example
|
|
107
|
+
- Session management
|
|
108
|
+
- And more!
|
|
109
|
+
|
|
110
|
+
## Browser Compatibility
|
|
111
|
+
|
|
112
|
+
The `getMsgerAPI()` function returns a browser-compatible implementation:
|
|
113
|
+
|
|
114
|
+
- **Data persistence**: Uses localStorage in both msger and browser
|
|
115
|
+
- **Window control**: No-op in browser (except `setTitle` updates document.title)
|
|
116
|
+
- **File system**: Not available in browser (`fs` is undefined)
|
|
117
|
+
|
|
118
|
+
This allows you to write code once that works in both environments!
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
ISC
|