Files
NexusOS/bin/nexus_window.py
T

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())