Electron-Prototyp: eigenes App-Fenster statt Tauri/WebKitGTK
Ersetzt den Tauri-Webview-Weg testweise durch eine Electron-Shell (randlos, ohne native Menüleiste, wie chromium-shell.sh), damit die WASM/WebGPU-Engine zuverlässig laeuft statt in WebKitGTK. Rust-Backend nicht noetig, da compute_joins einen TS-Fallback hat. npm run electron zum Starten.
This commit is contained in:
+20
-7
@@ -73,13 +73,26 @@ integrierter Engine-Viewport möglich). Die Engine-Rust-Crates sind in einem sp
|
||||
Schritt 1:1 wiederverwendbar; nur die dünne WASM-Bindeschicht wäre dann Wegwerf. All-native
|
||||
bleibt legitimes Fernziel, ist aber KEIN Weg zurück zu Tauri (Tauri IST der Webview-Shell).
|
||||
|
||||
>>> NÄCHSTER KONKRETER SCHRITT (neue Session zuerst): Electron-Prototyp. Nur additiv:
|
||||
`electron` als devDep, ~30-Zeilen `main.js` (BrowserWindow + `app.commandLine.appendSwitch`
|
||||
für WebGPU: `enable-unsafe-webgpu` + `enable-features=Vulkan` — dieselben Flags wie
|
||||
`scripts/chromium-shell.sh`), lädt den Vite-Server (dev) bzw. `dist` (prod), npm-Script
|
||||
`electron`. Verifizieren: App startet als eigenes Fenster, `?engine=wasm` rendert den
|
||||
Engine-Viewport (WebGPU in Electron = wie Chromium). Rust-Backend NICHT nötig — `compute_joins`
|
||||
hat TS-Fallback. Risikoarm, ~1 Session. Danach: render3d-WASM, Doppeltext-Fix.<<<
|
||||
>>> ELECTRON-PROTOTYP: FERTIG (2026-07-02). <<<
|
||||
`electron` als devDep, `scripts/electron-main.cjs` (BrowserWindow, `Menu.setApplicationMenu(null)`
|
||||
+ `frame:false`/`autoHideMenuBar` für randloses Fenster wie chromium-shell.sh, WebGPU-Flags
|
||||
`enable-unsafe-webgpu`+`enable-features=Vulkan`), `scripts/electron-shell.sh` (Dev-Server-Guard
|
||||
wie chromium-shell.sh), npm-Script `npm run electron`. Verifiziert per Screenshot: App startet
|
||||
als eigenes randloses Fenster, lädt den echten Grundriss (nicht leer). WICHTIG:
|
||||
- **Datei muss `.cjs` sein** (`package.json` hat `"type":"module"`, Electron-Main läuft als CJS).
|
||||
- **`ELECTRON_RUN_AS_NODE=1`** kann aus dem umgebenden Prozess (z.B. VSCode-Electron-Host)
|
||||
vererbt sein — zwingt Electron in den Node-Modus (`require('electron')` liefert nur einen
|
||||
Pfad-String statt `{app,...}` → `app` ist undefined). Immer mit `env -u ELECTRON_RUN_AS_NODE`
|
||||
starten, falls das Fenster nicht öffnet / `app.commandLine` undefined ist.
|
||||
- **WebGPU/`?engine=wasm` in Electron auf diesem System (niri/Wayland) fällt auf WebGL2 zurück**
|
||||
(Ozone-Wayland+Vulkan-Warnung beim Start). `--ozone-platform=x11` GEHT NICHT (bricht die
|
||||
Fenstererstellung komplett — GetGeometry/Vulkan-Surface-Fehler). System-Chromium
|
||||
(`chromium-shell.sh`) rendert die WASM-Engine hingegen nachweislich (siehe [[wasm-engine-viewport]]-
|
||||
Notizen); die verwendete Electron-Version (Paket sagt ^43, `--version` meldet v24 — Versions-
|
||||
Mismatch, ggf. stale Binary-Cache) könnte ein älteres/anders konfiguriertes Chromium mitbringen.
|
||||
TODO nächste Session: Electron-Version/Ozone-Flags weiter untersuchen, bevor der Prototyp der
|
||||
primäre Dev-Weg wird — bis dahin bleibt WebGL2-Fallback der Standardpfad, funktional unverändert.
|
||||
Danach: render3d-WASM, Doppeltext-Fix.<<<
|
||||
Klarstellung an den User (er fragte, ob Webview = „billig"): NEIN — Figma (eigene C++/WASM-Engine
|
||||
im Web-Shell), Onshape, VS Code zeigen, dass „eigene Engine + Web-UI" Top-Tier-Architektur ist.
|
||||
CAD/BIM-Substanz = Modell + Engine + Normen (haben wir: parametrische Wände, SIA 416, DOSSIER-
|
||||
|
||||
Generated
+135
@@ -27,6 +27,7 @@
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/three": "^0.169.0",
|
||||
"@vitejs/plugin-react": "^4.3.2",
|
||||
"electron": "^43.0.0",
|
||||
"playwright": "^1.61.1",
|
||||
"puppeteer": "^25.2.1",
|
||||
"typescript": "^5.6.2",
|
||||
@@ -326,6 +327,50 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron-internal/extract-zip": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@electron-internal/extract-zip/-/extract-zip-1.0.4.tgz",
|
||||
"integrity": "sha512-Zr1Vs7E9tpCNhZHDAbFVXc2gEVCG9RqPDjrno5+bdgB6LRAuvgyMHJut4NCVyYwtAieapMzc3fiQ3CSTi75ARg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/get": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@electron/get/-/get-5.0.0.tgz",
|
||||
"integrity": "sha512-pjoBpru1KdEtcExBnuHAP1cAc/5faoedw0hzJkL3o4/IJp7HNF1+fbrdxT3gMYRX2oJfvnA/WXeCTVQpYYxyJA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "^4.1.1",
|
||||
"env-paths": "^3.0.0",
|
||||
"graceful-fs": "^4.2.11",
|
||||
"progress": "^2.0.3",
|
||||
"semver": "^7.6.3",
|
||||
"sumchecker": "^3.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"undici": "^7.24.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/get/node_modules/semver": {
|
||||
"version": "7.8.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
|
||||
"integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/core": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz",
|
||||
@@ -1885,6 +1930,16 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.2.tgz",
|
||||
"integrity": "sha512-fRa09kZTgu8o71KFcDjUFuc7F+dEbZYZmkI0mg5YBTRs0yMKjYHsq/c0urDKeDb+D5qVgXOdFcuu+DZPKOITwA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~7.18.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/pako": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.4.tgz",
|
||||
@@ -2379,6 +2434,25 @@
|
||||
"loglevel": "^1.7.1"
|
||||
}
|
||||
},
|
||||
"node_modules/electron": {
|
||||
"version": "43.0.0",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-43.0.0.tgz",
|
||||
"integrity": "sha512-PV60GsWU6qufhuOhw3n+Yix3WPDcqDtBqE8orbEQGQGHEkgp9o/JCPgb7L4vIL0r1HnfPdqSRtboOTqbDkcFDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@electron-internal/extract-zip": "^1.0.1",
|
||||
"@electron/get": "^5.0.0",
|
||||
"@types/node": "^24.9.0"
|
||||
},
|
||||
"bin": {
|
||||
"electron": "cli.js",
|
||||
"install-electron": "install.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 22.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.380",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.380.tgz",
|
||||
@@ -2393,6 +2467,19 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/env-paths": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz",
|
||||
"integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/es-module-lexer": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.2.0.tgz",
|
||||
@@ -2558,6 +2645,13 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/html2canvas": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
|
||||
@@ -3248,6 +3342,16 @@
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/progress": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
||||
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/puppeteer": {
|
||||
"version": "25.2.1",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-25.2.1.tgz",
|
||||
@@ -3590,6 +3694,19 @@
|
||||
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/sumchecker": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz",
|
||||
"integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"debug": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/svg-pathdata": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
|
||||
@@ -3740,6 +3857,24 @@
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "7.28.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz",
|
||||
"integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=20.18.1"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.18.2",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
|
||||
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/update-browserslist-db": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"tauri:build": "tauri build",
|
||||
"dump:native": "node scripts/dump-native-scene.mjs",
|
||||
"shell": "scripts/chromium-shell.sh",
|
||||
"electron": "scripts/electron-shell.sh",
|
||||
"build:engine": "wasm-pack build src-tauri/render2d --release --target web --out-dir ../../src/engine/pkg --out-name render2d --no-default-features --features web"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -36,6 +37,7 @@
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/three": "^0.169.0",
|
||||
"@vitejs/plugin-react": "^4.3.2",
|
||||
"electron": "^43.0.0",
|
||||
"playwright": "^1.61.1",
|
||||
"puppeteer": "^25.2.1",
|
||||
"typescript": "^5.6.2",
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
// electron-main.js — Electron-Prototyp-Shell für die CAD-App.
|
||||
//
|
||||
// Ersetzt WebKitGTK (Tauri-Linux-Webview) durch Chromium, damit WebGPU
|
||||
// (render2d-WASM-Engine, ?engine=wasm) zuverlässig läuft. Kein Rust-Backend
|
||||
// nötig: compute_joins hat einen TS-Fallback (src/compute/index.ts).
|
||||
|
||||
const { app, BrowserWindow, Menu } = require("electron");
|
||||
|
||||
// Randloses App-Fenster wie chromium-shell.sh (--app=…): keine native
|
||||
// Menüleiste (File/Edit/View/Window), kein Fensterrahmen.
|
||||
Menu.setApplicationMenu(null);
|
||||
|
||||
// Gleiche Flags wie scripts/chromium-shell.sh — WebGPU liegt unter Linux
|
||||
// hinter --enable-unsafe-webgpu, und WebGPU braucht das Vulkan-Backend.
|
||||
app.commandLine.appendSwitch("enable-unsafe-webgpu");
|
||||
app.commandLine.appendSwitch("enable-features", "Vulkan");
|
||||
|
||||
const DEV_URL = "http://localhost:5187";
|
||||
const isDev = !app.isPackaged;
|
||||
|
||||
function createWindow() {
|
||||
const win = new BrowserWindow({
|
||||
width: 1600,
|
||||
height: 1000,
|
||||
frame: false,
|
||||
autoHideMenuBar: true,
|
||||
webPreferences: {
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
},
|
||||
});
|
||||
|
||||
if (isDev) {
|
||||
win.loadURL(DEV_URL);
|
||||
} else {
|
||||
win.loadFile(require("node:path").join(__dirname, "..", "dist", "index.html"));
|
||||
}
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow);
|
||||
|
||||
app.on("window-all-closed", () => {
|
||||
if (process.platform !== "darwin") app.quit();
|
||||
});
|
||||
|
||||
app.on("activate", () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow();
|
||||
});
|
||||
Executable
+49
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env bash
|
||||
# electron-shell.sh — startet die CAD-Oberfläche im Electron-Prototyp-Fenster.
|
||||
#
|
||||
# Wie chromium-shell.sh: stellt sicher, dass der Vite-Dev-Server läuft, startet
|
||||
# ihn sonst selbst und beendet ihn wieder, sobald das Electron-Fenster schliesst.
|
||||
|
||||
set -u
|
||||
|
||||
PORT=5187
|
||||
URL="http://localhost:${PORT}"
|
||||
|
||||
server_is_up() {
|
||||
curl --silent --fail --max-time 1 --output /dev/null "${URL}"
|
||||
}
|
||||
|
||||
DEV_SERVER_PID=""
|
||||
|
||||
if server_is_up; then
|
||||
echo "electron-shell: Dev-Server läuft bereits auf ${URL}."
|
||||
else
|
||||
echo "electron-shell: starte Vite-Dev-Server (Port ${PORT}) …"
|
||||
npm run dev >/tmp/cad-electron-shell-dev.log 2>&1 &
|
||||
DEV_SERVER_PID=$!
|
||||
|
||||
ATTEMPTS=0
|
||||
MAX_ATTEMPTS=60
|
||||
until server_is_up; do
|
||||
ATTEMPTS=$((ATTEMPTS + 1))
|
||||
if [ "${ATTEMPTS}" -ge "${MAX_ATTEMPTS}" ]; then
|
||||
echo "electron-shell: Dev-Server antwortet nach ${MAX_ATTEMPTS}s nicht, Abbruch." >&2
|
||||
kill "${DEV_SERVER_PID}" 2>/dev/null
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
echo "electron-shell: Dev-Server bereit."
|
||||
fi
|
||||
|
||||
cleanup() {
|
||||
if [ -n "${DEV_SERVER_PID}" ]; then
|
||||
echo "electron-shell: beende selbst gestarteten Dev-Server (PID ${DEV_SERVER_PID}) …"
|
||||
kill "${DEV_SERVER_PID}" 2>/dev/null
|
||||
wait "${DEV_SERVER_PID}" 2>/dev/null
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
echo "electron-shell: öffne Electron-Fenster …"
|
||||
npx electron "$(dirname "$0")/electron-main.cjs"
|
||||
Reference in New Issue
Block a user