73 lines
2.2 KiB
Python
73 lines
2.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Open the NexusOS UI in a native window.
|
|
|
|
Uses pywebview, which renders via the WebView2 runtime on Windows (already
|
|
present on Win10/11) -- a real app window with no browser chrome and none of the
|
|
Edge --app profile cold-start. Blocks until the window is closed; the launcher
|
|
waits on this process and stops the services when it exits.
|
|
|
|
Falls back to the default browser if pywebview/WebView2 is unavailable, staying
|
|
alive so the launcher doesn't tear the services down underneath it.
|
|
"""
|
|
import sys
|
|
import time
|
|
import urllib.request
|
|
|
|
URL = "http://localhost:8000"
|
|
|
|
|
|
def _wait_for_backend(timeout: float = 40.0) -> bool:
|
|
"""Poll /status until the backend answers, so the window never loads before
|
|
the server is up (which shows a localhost error the webview won't retry)."""
|
|
status_url = URL.rstrip("/") + "/status"
|
|
deadline = time.time() + timeout
|
|
while time.time() < deadline:
|
|
try:
|
|
with urllib.request.urlopen(status_url, timeout=2) as r:
|
|
if r.status == 200:
|
|
return True
|
|
except Exception:
|
|
time.sleep(1)
|
|
return False
|
|
|
|
|
|
def main() -> int:
|
|
try:
|
|
import webview
|
|
except Exception as e: # pywebview not installed
|
|
return _browser_fallback(f"pywebview unavailable ({e})")
|
|
|
|
if not _wait_for_backend():
|
|
print("[nexus] backend not reachable on :8000 after 40s.", file=sys.stderr)
|
|
|
|
try:
|
|
webview.create_window(
|
|
"NexusOS",
|
|
URL,
|
|
width=1200,
|
|
height=800,
|
|
min_size=(900, 600),
|
|
)
|
|
webview.start() # blocks until the window is closed
|
|
return 0
|
|
except Exception as e: # no WebView2 runtime / backend failure
|
|
return _browser_fallback(f"native window failed ({e})")
|
|
|
|
|
|
def _browser_fallback(reason: str) -> int:
|
|
import webbrowser
|
|
|
|
print(f"[nexus] {reason}; opening default browser instead.", file=sys.stderr)
|
|
webbrowser.open(URL)
|
|
# Stay alive so the launcher keeps the services up. The user stops NexusOS
|
|
# by closing the launcher (or the browser tab, then the services idle out).
|
|
try:
|
|
while True:
|
|
time.sleep(3600)
|
|
except KeyboardInterrupt:
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|