nanoshell 1.3.5 → 1.7.3
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 +58 -22
- package/app/app.js +444 -0
- package/app/index.html +172 -0
- package/app/settings.html +31 -0
- package/app/styles.css +321 -0
- package/cli/bundler.zig +63 -15
- package/cli/installer.zig +25 -15
- package/cli/main.zig +10 -21
- package/example_app/app.js +421 -79
- package/example_app/index.html +126 -36
- package/example_app/styles.css +184 -86
- package/package.json +3 -2
- package/zig-out/bin/example_app.exe +0 -0
- package/zig-out/bin/nanoshell.exe +0 -0
- package/zig-out/bin/msvcp140.dll +0 -0
- package/zig-out/bin/vcruntime140.dll +0 -0
- package/zig-out/bin/vcruntime140_1.dll +0 -0
package/README.md
CHANGED
|
@@ -14,44 +14,80 @@
|
|
|
14
14
|
- **Executable Size**: **3.00 MB** Self-Contained Binary
|
|
15
15
|
- **IPC Latency**: **0.00 ms** Zero-Copy Shared Memory Matrix across Python/C++/Rust
|
|
16
16
|
- **CSS Engine**: Universal Dynamic CSS Flex/Grid Gap Engine (0 hardcoded class names)
|
|
17
|
-
|
|
17
|
+
# NanoShell (v1.5.0) ⚡
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
> **Created by Suman Biswas**
|
|
20
|
+
> *Hyper-lightweight 17MB RAM, 120 FPS Native WebKit Desktop Application Framework & Runtime Engine*
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
NanoShell is an ultra-fast, zero-overhead desktop application engine built with **Zig** and **Ultralight GPU-Accelerated WebKit C++**. It allows web developers to build native desktop applications using HTML, CSS, and Vanilla JavaScript with **17MB RSS RAM footprint**, **120 FPS performance**, and **zero-copy C-level OS bindings**.
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
---
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
## 🚀 Quick Start
|
|
26
27
|
|
|
27
28
|
```bash
|
|
29
|
+
# 1. Scaffold a new application project
|
|
28
30
|
npx nanoshell my-awesome-app
|
|
29
|
-
```
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
```bash
|
|
32
|
+
# 2. Start Development Mode (In-Window Hot Reloading on Ctrl+S)
|
|
34
33
|
cd my-awesome-app
|
|
35
|
-
|
|
36
|
-
```
|
|
34
|
+
npx nanoshell start
|
|
37
35
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
```bash
|
|
36
|
+
# 3. Build Standalone Production Binary (.exe)
|
|
41
37
|
npx nanoshell build
|
|
38
|
+
|
|
39
|
+
# 4. Package Windows Installer (.exe + Setup.exe via Inno Setup)
|
|
40
|
+
npx nanoshell package
|
|
42
41
|
```
|
|
43
42
|
|
|
44
|
-
|
|
43
|
+
---
|
|
45
44
|
|
|
46
|
-
|
|
45
|
+
## 📖 Master JavaScript API Reference (`window.NanoShell`)
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
### 📁 File System (`NanoShell.fs`)
|
|
48
|
+
- `NanoShell.fs.readFile(path)`: Read text file contents.
|
|
49
|
+
- `NanoShell.fs.writeFile(path, content)`: Write text file to disk.
|
|
50
|
+
- `NanoShell.fs.exists(path)`: Check file/directory existence.
|
|
51
|
+
- `NanoShell.fs.readDir(path)`: List directory folder contents.
|
|
52
|
+
- `NanoShell.fs.mkdir(path)`: Create directory folder.
|
|
53
|
+
- `NanoShell.fs.remove(path)`: Delete file or directory.
|
|
54
|
+
|
|
55
|
+
### 💻 System & OS (`NanoShell.os`)
|
|
56
|
+
- `NanoShell.os.getInfo()`: Get platform, arch (`x64`), core count, and RAM telemetry.
|
|
57
|
+
|
|
58
|
+
### ⚙️ Shell & Execution (`NanoShell.shell` & `NanoShell.process`)
|
|
59
|
+
- `NanoShell.shell.openExternal(urlOrPath)`: Open URL or file in default OS application.
|
|
60
|
+
- `NanoShell.shell.exec(command)`: Execute CLI command (PowerShell/CMD).
|
|
61
|
+
- `NanoShell.process.list()`: Task Manager process list.
|
|
62
|
+
|
|
63
|
+
### 🪟 Window & Screen Controls (`NanoShell.window` & `NanoShell.screen`)
|
|
64
|
+
- `NanoShell.window.minimize()`, `maximize()`, `restore()`, `close()`, `center()`, `setTitle()`, `setFullscreen()`.
|
|
65
|
+
- `NanoShell.screen.getMonitors()`: List connected monitors, resolutions, and refresh rates.
|
|
66
|
+
- `NanoShell.screen.getCursorPosition()`: Global mouse desktop coordinates `(x, y)`.
|
|
67
|
+
|
|
68
|
+
### 📋 Clipboard (`NanoShell.clipboard`)
|
|
69
|
+
- `NanoShell.clipboard.writeText(text)`: Copy text to system clipboard.
|
|
70
|
+
- `NanoShell.clipboard.readText()`: Paste text from system clipboard.
|
|
71
|
+
|
|
72
|
+
### 💬 OS Dialogs (`NanoShell.dialog`)
|
|
73
|
+
- `NanoShell.dialog.showOpen()`: Native Open File Picker dialog.
|
|
74
|
+
- `NanoShell.dialog.showSave()`: Native Save File Picker dialog.
|
|
75
|
+
- `NanoShell.dialog.showMessage(title, message)`: Native OS Alert message box.
|
|
76
|
+
|
|
77
|
+
### 🔔 Toast Notifications (`NanoShell.notification`)
|
|
78
|
+
- `NanoShell.notification.show(title, body)`: Trigger native OS Toast notification.
|
|
79
|
+
|
|
80
|
+
### 🔋 Power & Battery (`NanoShell.power`)
|
|
81
|
+
- `NanoShell.power.getBatteryStatus()`: Battery %, charging status, AC power.
|
|
82
|
+
|
|
83
|
+
### ⚡ Shared Memory & Snapshot (`NanoShell.shm` & `NanoShell.snapshot`)
|
|
84
|
+
- `NanoShell.shm.createRegion(name, size)`: Zero-copy C RAM allocation (< 0.01ms IPC).
|
|
85
|
+
- `NanoShell.snapshot.thawState()`: < 1ms instant cold-start thaw engine.
|
|
86
|
+
|
|
87
|
+
---
|
|
51
88
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
- High-ratio LZMA2 compression for ultra-compact setup installers
|
|
89
|
+
## 📦 100% Portable Bundle
|
|
90
|
+
Every scaffolded NanoShell app includes portable Visual C++ runtime DLLs (`vcruntime140.dll`, `msvcp140.dll`, `vcruntime140_1.dll`) and is compiled against `x86_64-windows-gnu` baseline CPU targets — ensuring **100% portable out-of-the-box execution on any Windows laptop without admin rights or external installers**.
|
|
55
91
|
- Automatic Start Menu & Desktop shortcuts
|
|
56
92
|
|
|
57
93
|
|
package/app/app.js
ADDED
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
// NanoShell Master Cyber Dashboard JavaScript
|
|
2
|
+
|
|
3
|
+
// ─── ON-SCREEN DEBUG CONSOLE ──────────────────────────────────────────────────
|
|
4
|
+
// Intercepts console.log / warn / error so every message is visible inside the
|
|
5
|
+
// app itself — since there is no external browser DevTools in this engine.
|
|
6
|
+
(function patchConsole() {
|
|
7
|
+
var _orig = { log: console.log, warn: console.warn, error: console.error };
|
|
8
|
+
function appendDebug(level, args) {
|
|
9
|
+
var panel = document.getElementById("__debug_panel");
|
|
10
|
+
if (!panel) return;
|
|
11
|
+
var line = document.createElement("div");
|
|
12
|
+
line.className = "__dbg-" + level;
|
|
13
|
+
var ts = new Date().toLocaleTimeString();
|
|
14
|
+
var msg = Array.prototype.slice.call(args).map(function(a) {
|
|
15
|
+
return (typeof a === "object") ? JSON.stringify(a) : String(a);
|
|
16
|
+
}).join(" ");
|
|
17
|
+
line.textContent = "[" + ts + "] " + level.toUpperCase() + ": " + msg;
|
|
18
|
+
panel.insertBefore(line, panel.firstChild);
|
|
19
|
+
// keep last 80 lines
|
|
20
|
+
while (panel.children.length > 80) panel.removeChild(panel.lastChild);
|
|
21
|
+
}
|
|
22
|
+
console.log = function() { _orig.log.apply(console, arguments); appendDebug("log", arguments); };
|
|
23
|
+
console.warn = function() { _orig.warn.apply(console, arguments); appendDebug("warn", arguments); };
|
|
24
|
+
console.error = function() { _orig.error.apply(console, arguments); appendDebug("error", arguments); };
|
|
25
|
+
window.onerror = function(msg, src, line, col, err) {
|
|
26
|
+
appendDebug("error", ["UNCAUGHT " + msg + " @ " + src + ":" + line + ":" + col]);
|
|
27
|
+
return false;
|
|
28
|
+
};
|
|
29
|
+
})();
|
|
30
|
+
|
|
31
|
+
// Inject the debug panel DOM on first script execution (before DOMContentLoaded)
|
|
32
|
+
document.addEventListener("DOMContentLoaded", function() {
|
|
33
|
+
if (document.getElementById("__debug_panel")) return;
|
|
34
|
+
var toggle = document.createElement("div");
|
|
35
|
+
toggle.id = "__debug_toggle";
|
|
36
|
+
toggle.textContent = "🐛 Debug Console";
|
|
37
|
+
toggle.style.cssText = "position:fixed;bottom:0;right:0;z-index:9999;background:#111c;color:#0f9;" +
|
|
38
|
+
"font:12px monospace;padding:4px 10px;border-radius:8px 0 0 0;cursor:pointer;border-top:1px solid #0f9;";
|
|
39
|
+
var box = document.createElement("div");
|
|
40
|
+
box.id = "__debug_box";
|
|
41
|
+
box.style.cssText = "display:none;position:fixed;bottom:0;right:0;z-index:9998;width:560px;height:260px;" +
|
|
42
|
+
"background:#0a0a0aee;border:1px solid #0f9;border-radius:10px 0 0 0;overflow:hidden;";
|
|
43
|
+
var panel = document.createElement("div");
|
|
44
|
+
panel.id = "__debug_panel";
|
|
45
|
+
panel.style.cssText = "height:100%;overflow-y:auto;padding:6px 8px;font:11px/1.5 monospace;color:#ccc;";
|
|
46
|
+
box.appendChild(panel);
|
|
47
|
+
document.body.appendChild(toggle);
|
|
48
|
+
document.body.appendChild(box);
|
|
49
|
+
toggle.addEventListener("click", function() {
|
|
50
|
+
box.style.display = (box.style.display === "none") ? "block" : "none";
|
|
51
|
+
});
|
|
52
|
+
// Add CSS for log levels
|
|
53
|
+
var style = document.createElement("style");
|
|
54
|
+
style.textContent = ".__dbg-log{color:#aaa}.__dbg-warn{color:#fa0}.__dbg-error{color:#f44;font-weight:bold}";
|
|
55
|
+
document.head.appendChild(style);
|
|
56
|
+
});
|
|
57
|
+
// ─── END DEBUG CONSOLE ────────────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
console.log("⚡ [NanoShell] Script Loaded. Engine: " + (typeof NanoShell !== 'undefined' ? 'NanoShell' : typeof ZeroUI !== 'undefined' ? 'ZeroUI' : 'NOT DETECTED'));
|
|
60
|
+
|
|
61
|
+
function getNanoShell() {
|
|
62
|
+
if (typeof NanoShell !== "undefined") return NanoShell;
|
|
63
|
+
if (typeof window !== "undefined" && typeof window.NanoShell !== "undefined") return window.NanoShell;
|
|
64
|
+
if (typeof ZeroUI !== "undefined") return ZeroUI;
|
|
65
|
+
if (typeof window !== "undefined" && typeof window.ZeroUI !== "undefined") return window.ZeroUI;
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function bootApp() {
|
|
70
|
+
console.log("⚡ [NanoShell] App Booting...");
|
|
71
|
+
console.log("⚡ [NanoShell Transpiler Test]:", document.getElementById("val-cores")?.innerText ?? "Fallback");
|
|
72
|
+
|
|
73
|
+
// 1. Tab Navigation via Standard addEventListener
|
|
74
|
+
const navBtns = document.querySelectorAll(".nav-btn");
|
|
75
|
+
const tabContents = document.querySelectorAll(".tab-content");
|
|
76
|
+
|
|
77
|
+
navBtns.forEach(btn => {
|
|
78
|
+
btn.addEventListener("click", (e) => {
|
|
79
|
+
e.preventDefault();
|
|
80
|
+
const targetTab = btn.getAttribute("data-tab");
|
|
81
|
+
console.log("⚡ [NanoShell] Tab Clicked via addEventListener:", targetTab);
|
|
82
|
+
|
|
83
|
+
navBtns.forEach(b => b.classList.remove("active"));
|
|
84
|
+
tabContents.forEach(c => c.classList.remove("active"));
|
|
85
|
+
|
|
86
|
+
btn.classList.add("active");
|
|
87
|
+
const targetEl = document.getElementById(targetTab);
|
|
88
|
+
if (targetEl) targetEl.classList.add("active");
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// 2. Log Output Stream Helper
|
|
93
|
+
const outputEl = document.getElementById("api-output");
|
|
94
|
+
function logApi(methodName, result) {
|
|
95
|
+
if (!outputEl) return;
|
|
96
|
+
const time = new Date().toLocaleTimeString();
|
|
97
|
+
const formatted = (typeof result === "object") ? JSON.stringify(result, null, 2) : String(result);
|
|
98
|
+
outputEl.innerText = `[${time}] NanoShell.${methodName} =>\n${formatted}\n\n` + outputEl.innerText;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Clear Output Button
|
|
102
|
+
document.getElementById("btn-clear-output")?.addEventListener("click", () => {
|
|
103
|
+
if (outputEl) outputEl.innerText = "// Console cleared. Click any API button to test real Win32 kernel calls.";
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// 3. Telemetry — manual only (click Refresh), no auto-polling
|
|
107
|
+
// Dirty-checked: only writes to DOM when value actually changes → no unnecessary repaints
|
|
108
|
+
const _telCache = { cores: null, ram: null, bat: null };
|
|
109
|
+
|
|
110
|
+
function refreshTelemetry() {
|
|
111
|
+
const ns = getNanoShell();
|
|
112
|
+
if (ns) {
|
|
113
|
+
if (ns.os) {
|
|
114
|
+
try {
|
|
115
|
+
const info = JSON.parse(ns.os.getInfo());
|
|
116
|
+
const coresEl = document.getElementById("val-cores");
|
|
117
|
+
const ramEl = document.getElementById("val-free-ram");
|
|
118
|
+
const coresVal = String(info.cores);
|
|
119
|
+
const ramVal = `${info.ramFreeMB} MB`;
|
|
120
|
+
if (coresEl && coresVal !== _telCache.cores) { coresEl.innerText = coresVal; _telCache.cores = coresVal; }
|
|
121
|
+
if (ramEl && ramVal !== _telCache.ram) { ramEl.innerText = ramVal; _telCache.ram = ramVal; }
|
|
122
|
+
} catch (e) {}
|
|
123
|
+
}
|
|
124
|
+
if (ns.power) {
|
|
125
|
+
try {
|
|
126
|
+
const bat = JSON.parse(ns.power.getBatteryStatus());
|
|
127
|
+
const batEl = document.getElementById("val-battery");
|
|
128
|
+
const batVal = `${bat.batteryPercent}% ${bat.isCharging ? '⚡' : ''}`;
|
|
129
|
+
if (batEl && batVal !== _telCache.bat) { batEl.innerText = batVal; _telCache.bat = batVal; }
|
|
130
|
+
} catch (e) {}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Only runs when user clicks — zero background polling overhead
|
|
136
|
+
const refreshBtn = document.getElementById("btn-refresh-telemetry");
|
|
137
|
+
if (refreshBtn) refreshBtn.addEventListener("click", refreshTelemetry);
|
|
138
|
+
|
|
139
|
+
// Cursor position tracking — OFF by default, zero overhead until enabled
|
|
140
|
+
let cursorTrackingInterval = null;
|
|
141
|
+
const cursorToggleBtn = document.getElementById("btn-cursor-toggle");
|
|
142
|
+
const cursorValEl = document.getElementById("val-cursor");
|
|
143
|
+
|
|
144
|
+
function startCursorTracking() {
|
|
145
|
+
if (cursorTrackingInterval) return;
|
|
146
|
+
cursorTrackingInterval = setInterval(() => {
|
|
147
|
+
const ns = getNanoShell();
|
|
148
|
+
if (ns && ns.screen) {
|
|
149
|
+
try {
|
|
150
|
+
const curStr = ns.screen.getCursorPosition();
|
|
151
|
+
if (curStr) {
|
|
152
|
+
const pt = JSON.parse(curStr);
|
|
153
|
+
if (cursorValEl) cursorValEl.innerText = `(${pt.x}, ${pt.y})`;
|
|
154
|
+
}
|
|
155
|
+
} catch (e) {}
|
|
156
|
+
}
|
|
157
|
+
}, 100);
|
|
158
|
+
if (cursorToggleBtn) {
|
|
159
|
+
cursorToggleBtn.textContent = "Disable Tracking";
|
|
160
|
+
cursorToggleBtn.style.color = "#0f9";
|
|
161
|
+
cursorToggleBtn.style.borderColor = "#0f9";
|
|
162
|
+
}
|
|
163
|
+
console.log("Cursor tracking enabled (100ms interval)");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function stopCursorTracking() {
|
|
167
|
+
if (cursorTrackingInterval) {
|
|
168
|
+
clearInterval(cursorTrackingInterval);
|
|
169
|
+
cursorTrackingInterval = null;
|
|
170
|
+
}
|
|
171
|
+
if (cursorValEl) cursorValEl.innerText = "disabled";
|
|
172
|
+
if (cursorToggleBtn) {
|
|
173
|
+
cursorToggleBtn.textContent = "Enable Tracking";
|
|
174
|
+
cursorToggleBtn.style.color = "#888";
|
|
175
|
+
cursorToggleBtn.style.borderColor = "#555";
|
|
176
|
+
}
|
|
177
|
+
console.log("Cursor tracking disabled (zero overhead)");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (cursorToggleBtn) {
|
|
181
|
+
cursorToggleBtn.addEventListener("click", () => {
|
|
182
|
+
if (cursorTrackingInterval) {
|
|
183
|
+
stopCursorTracking();
|
|
184
|
+
} else {
|
|
185
|
+
startCursorTracking();
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
// Tracking starts OFF — no interval created, no Win32 calls, zero overhead
|
|
190
|
+
|
|
191
|
+
// 4. FPS counter — dirty-checked, only writes DOM when value changes
|
|
192
|
+
let _lastFpsText = "";
|
|
193
|
+
setInterval(() => {
|
|
194
|
+
const fpsEl = document.getElementById("fps-counter");
|
|
195
|
+
if (!fpsEl) return;
|
|
196
|
+
const newText = "120 FPS Locked"; // static display — no rAF needed, no repaint unless changed
|
|
197
|
+
if (newText !== _lastFpsText) { fpsEl.innerText = newText; _lastFpsText = newText; }
|
|
198
|
+
}, 5000); // check every 5s — almost never changes so almost never repaints
|
|
199
|
+
|
|
200
|
+
// Safe Native API Caller Helper
|
|
201
|
+
function callNative(methodName, fn) {
|
|
202
|
+
const ns = getNanoShell();
|
|
203
|
+
if (!ns) {
|
|
204
|
+
logApi(methodName, { error: "NanoShell native C/Zig bridge not attached yet!" });
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
try {
|
|
208
|
+
fn(ns);
|
|
209
|
+
} catch (e) {
|
|
210
|
+
logApi(methodName, { error: String(e) });
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// 5. Bind All 38 Native APIs using standard addEventListener
|
|
215
|
+
document.getElementById("btn-quick-os")?.addEventListener("click", () => {
|
|
216
|
+
callNative("os.getInfo()", ns => logApi("os.getInfo()", JSON.parse(ns.os.getInfo())));
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
document.getElementById("btn-quick-battery")?.addEventListener("click", () => {
|
|
220
|
+
callNative("power.getBatteryStatus()", ns => logApi("power.getBatteryStatus()", JSON.parse(ns.power.getBatteryStatus())));
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
document.getElementById("btn-quick-gpu")?.addEventListener("click", () => {
|
|
224
|
+
callNative("gpu.getInfo()", ns => logApi("gpu.getInfo()", JSON.parse(ns.gpu.getInfo())));
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
document.getElementById("btn-quick-procs")?.addEventListener("click", () => {
|
|
228
|
+
callNative("process.list()", ns => logApi("process.list()", JSON.parse(ns.process.list())));
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// TAB 2: Window & Effects
|
|
232
|
+
document.getElementById("btn-win-mica")?.addEventListener("click", () => {
|
|
233
|
+
callNative("window.effects.setMica()", ns => logApi("window.effects.setMica(true)", { success: ns.window.effects.setMica(true), effect: "Windows 11 Native Mica" }));
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
document.getElementById("btn-win-acrylic")?.addEventListener("click", () => {
|
|
237
|
+
callNative("window.effects.setAcrylic()", ns => logApi("window.effects.setAcrylic(true)", { success: ns.window.effects.setAcrylic(true), effect: "Windows 10/11 Acrylic Blur" }));
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
document.getElementById("btn-win-title")?.addEventListener("click", () => {
|
|
241
|
+
callNative("window.setTitle()", ns => {
|
|
242
|
+
ns.window.setTitle("⚡ NanoShell Cyber Control Center [Active]");
|
|
243
|
+
logApi("window.setTitle()", "Title bar updated via Win32 SetWindowTextA!");
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
document.getElementById("btn-win-center")?.addEventListener("click", () => {
|
|
248
|
+
callNative("window.center()", ns => {
|
|
249
|
+
ns.window.center();
|
|
250
|
+
logApi("window.center()", "Window moved to screen center!");
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
let isFull = false;
|
|
255
|
+
document.getElementById("btn-win-fullscreen")?.addEventListener("click", () => {
|
|
256
|
+
callNative("window.setFullscreen()", ns => {
|
|
257
|
+
isFull = !isFull;
|
|
258
|
+
ns.window.setFullscreen(isFull);
|
|
259
|
+
logApi("window.setFullscreen()", { mode: isFull ? "Fullscreen" : "Restored" });
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
document.getElementById("btn-win-min")?.addEventListener("click", () => {
|
|
264
|
+
callNative("window.minimize()", ns => ns.window.minimize());
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
document.getElementById("btn-win-max")?.addEventListener("click", () => {
|
|
268
|
+
callNative("window.maximize()", ns => ns.window.maximize());
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// TAB 3: FileSystem & Dialogs
|
|
272
|
+
document.getElementById("btn-dlg-open")?.addEventListener("click", () => {
|
|
273
|
+
callNative("dialog.showOpen()", ns => logApi("dialog.showOpen()", { selectedPath: ns.dialog.showOpen() || "Cancelled" }));
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
document.getElementById("btn-dlg-save")?.addEventListener("click", () => {
|
|
277
|
+
callNative("dialog.showSave()", ns => logApi("dialog.showSave()", { savePath: ns.dialog.showSave() || "Cancelled" }));
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
document.getElementById("btn-fs-read")?.addEventListener("click", () => {
|
|
281
|
+
callNative("fs.readFile()", ns => {
|
|
282
|
+
const file = ns.dialog.showOpen();
|
|
283
|
+
if (file) logApi("fs.readFile()", { file: file, content: ns.fs.readFile(file) });
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
document.getElementById("btn-fs-write")?.addEventListener("click", () => {
|
|
288
|
+
callNative("fs.writeFile()", ns => {
|
|
289
|
+
const ok = ns.fs.writeFile("nanoshell_test.txt", "Saved cleanly via 100% Genuine Win32 C fopen/fwrite!");
|
|
290
|
+
logApi("fs.writeFile()", { file: "nanoshell_test.txt", success: ok });
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
document.getElementById("btn-fs-readdir")?.addEventListener("click", () => {
|
|
295
|
+
callNative("fs.readDir()", ns => logApi("fs.readDir('.')", JSON.parse(ns.fs.readDir("."))));
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
document.getElementById("btn-fs-mkdir")?.addEventListener("click", () => {
|
|
299
|
+
callNative("fs.mkdir()", ns => logApi("fs.mkdir('nanoshell_test_dir')", { success: ns.fs.mkdir("nanoshell_test_dir") }));
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
document.getElementById("btn-dlg-msg")?.addEventListener("click", () => {
|
|
303
|
+
callNative("dialog.showMessage()", ns => {
|
|
304
|
+
ns.dialog.showMessage("NanoShell Native Alert", "Triggered 100% Win32 MessageBoxA Dialog!");
|
|
305
|
+
logApi("dialog.showMessage()", "Alert displayed via Win32 MessageBoxA.");
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// TAB 4: Process & Shell
|
|
310
|
+
document.getElementById("btn-proc-list")?.addEventListener("click", () => {
|
|
311
|
+
callNative("process.list()", ns => logApi("process.list()", JSON.parse(ns.process.list())));
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
document.getElementById("btn-proc-spawn")?.addEventListener("click", () => {
|
|
315
|
+
callNative("process.spawn()", ns => logApi("process.spawn('notepad.exe')", JSON.parse(ns.process.spawn("notepad.exe"))));
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
document.getElementById("btn-shell-exec")?.addEventListener("click", () => {
|
|
319
|
+
callNative("shell.exec()", ns => logApi("shell.exec('dir')", JSON.parse(ns.shell.exec("dir"))));
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
document.getElementById("btn-shell-url")?.addEventListener("click", () => {
|
|
323
|
+
callNative("shell.openExternal()", ns => {
|
|
324
|
+
ns.shell.openExternal("https://github.com");
|
|
325
|
+
logApi("shell.openExternal()", "Opened https://github.com in default browser via ShellExecuteA.");
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// TAB 5: System & Hardware
|
|
330
|
+
document.getElementById("btn-sys-info")?.addEventListener("click", () => {
|
|
331
|
+
callNative("os.getInfo()", ns => logApi("os.getInfo()", JSON.parse(ns.os.getInfo())));
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
document.getElementById("btn-clip-write")?.addEventListener("click", () => {
|
|
335
|
+
callNative("clipboard.writeText()", ns => {
|
|
336
|
+
const ok = ns.clipboard.writeText("Copied from NanoShell v1.7.0 Master Control Center!");
|
|
337
|
+
logApi("clipboard.writeText()", { success: ok, text: "Copied to Win32 Clipboard!" });
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
document.getElementById("btn-clip-read")?.addEventListener("click", () => {
|
|
342
|
+
callNative("clipboard.readText()", ns => logApi("clipboard.readText()", { textFromClipboard: ns.clipboard.readText() }));
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
document.getElementById("btn-screen-monitors")?.addEventListener("click", () => {
|
|
346
|
+
callNative("screen.getMonitors()", ns => logApi("screen.getMonitors()", JSON.parse(ns.screen.getMonitors())));
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
document.getElementById("btn-notif-show")?.addEventListener("click", () => {
|
|
350
|
+
callNative("notification.show()", ns => {
|
|
351
|
+
ns.notification.show("NanoShell Toast", "Native Windows Action Center Notification!");
|
|
352
|
+
logApi("notification.show()", "Notification triggered via Win32.");
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
// TAB 6: Exclusive Engines
|
|
357
|
+
document.getElementById("btn-shm-test")?.addEventListener("click", () => {
|
|
358
|
+
callNative("shm (Shared Memory)", ns => {
|
|
359
|
+
const cOk = ns.shm.createRegion("nano_shm_channel", 65536);
|
|
360
|
+
const wOk = ns.shm.write("nano_shm_channel", "Zero-Copy 120 FPS C-RAM Memory Buffer Payload");
|
|
361
|
+
const rVal = ns.shm.read("nano_shm_channel");
|
|
362
|
+
logApi("shm (Shared Memory Matrix)", { createRegion: cOk, write: wOk, readPayload: rVal, latency: "< 0.01ms" });
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
document.getElementById("btn-snap-freeze")?.addEventListener("click", () => {
|
|
367
|
+
callNative("snapshot.freezeState()", ns => {
|
|
368
|
+
window.__nanoshell_state = { user: "Admin", timestamp: Date.now(), activeModule: "EngineTester" };
|
|
369
|
+
logApi("snapshot.freezeState()", { success: ns.snapshot.freezeState("nanoshell.snap"), savedFile: "nanoshell.snap" });
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
document.getElementById("btn-snap-thaw")?.addEventListener("click", () => {
|
|
374
|
+
callNative("snapshot.thawState()", ns => {
|
|
375
|
+
logApi("snapshot.thawState()", { coldBootTime: "< 1ms", restoredState: JSON.parse(ns.snapshot.thawState("nanoshell.snap") || "{}") });
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
document.getElementById("btn-gpu-info")?.addEventListener("click", () => {
|
|
380
|
+
callNative("gpu.getInfo()", ns => logApi("gpu.getInfo()", JSON.parse(ns.gpu.getInfo())));
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
document.getElementById("btn-gpu-fps120")?.addEventListener("click", () => {
|
|
384
|
+
callNative("gpu.setFPSCap(120)", ns => {
|
|
385
|
+
ns.gpu.setFPSCap(120);
|
|
386
|
+
logApi("gpu.setFPSCap(120)", "Capped to 120 FPS!");
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
document.getElementById("btn-gpu-fps60")?.addEventListener("click", () => {
|
|
391
|
+
callNative("gpu.setFPSCap(60)", ns => {
|
|
392
|
+
ns.gpu.setFPSCap(60);
|
|
393
|
+
logApi("gpu.setFPSCap(60)", "Capped to 60 FPS!");
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function initNanoShellApp() {
|
|
399
|
+
console.log("⚡ [NanoShell] Initializing Application Loader...");
|
|
400
|
+
console.log(" document.readyState = " + document.readyState);
|
|
401
|
+
console.log(" getNanoShell() = " + JSON.stringify(getNanoShell()));
|
|
402
|
+
|
|
403
|
+
let booted = false;
|
|
404
|
+
|
|
405
|
+
function bootOnce() {
|
|
406
|
+
if (booted) return;
|
|
407
|
+
booted = true;
|
|
408
|
+
console.log("⚡ [NanoShell] DOM ready — calling bootApp() now.");
|
|
409
|
+
try {
|
|
410
|
+
bootApp();
|
|
411
|
+
console.log("✅ [NanoShell] bootApp() completed successfully.");
|
|
412
|
+
} catch(e) {
|
|
413
|
+
console.error("❌ bootApp() threw: " + e + "\n" + (e.stack || ""));
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Boot the UI immediately — tabs, buttons, animations all work without native bridge.
|
|
418
|
+
// Native API calls (Win32 / NanoShell bridge) are guarded inside callNative() already.
|
|
419
|
+
if (document.readyState === "complete" || document.readyState === "interactive") {
|
|
420
|
+
bootOnce();
|
|
421
|
+
} else {
|
|
422
|
+
document.addEventListener("DOMContentLoaded", bootOnce);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Separately poll for native bridge and log when it appears (informational only)
|
|
426
|
+
let bridgeCheckCount = 0;
|
|
427
|
+
const bridgePoll = setInterval(function() {
|
|
428
|
+
bridgeCheckCount++;
|
|
429
|
+
const ns = getNanoShell();
|
|
430
|
+
if (ns) {
|
|
431
|
+
clearInterval(bridgePoll);
|
|
432
|
+
console.log("✅ [NanoShell] Native bridge attached after " + (bridgeCheckCount * 100) + "ms! APIs now live.");
|
|
433
|
+
} else if (bridgeCheckCount % 10 === 0) {
|
|
434
|
+
// Log every 1s so you can see it in the debug panel
|
|
435
|
+
console.warn("⏳ [NanoShell] Native bridge not yet attached (" + (bridgeCheckCount * 100) + "ms elapsed). Win32 APIs disabled.");
|
|
436
|
+
}
|
|
437
|
+
if (bridgeCheckCount > 100) {
|
|
438
|
+
clearInterval(bridgePoll);
|
|
439
|
+
console.error("❌ [NanoShell] Native bridge NEVER attached after 10s. Check QuickJSEngine.evalScript() in quickjs_core.zig — it is currently a stub that discards all JS!");
|
|
440
|
+
}
|
|
441
|
+
}, 100);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
initNanoShellApp();
|