#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ AZA Empfang - Schlanke Desktop-Huelle fuer die Empfangs-Weboberflaeche. Laedt die Empfangs-Seite in einem WebView-Fenster. """ import json import os import ssl import sys import threading import webbrowser _APP_TITLE = "AZA Empfang" _MIN_SIZE = (380, 500) _DEFAULT_W, _DEFAULT_H = 480, 820 _PUBLIC_EMPFANG_URL = "https://empfang.aza-medwork.ch" def _data_dir(): if getattr(sys, "frozen", False): return sys._MEIPASS return os.path.dirname(os.path.abspath(__file__)) def _user_dir(): if getattr(sys, "frozen", False): return os.path.dirname(sys.executable) return os.path.dirname(os.path.abspath(__file__)) def _empfang_url(): try: p = os.path.join(_data_dir(), "backend_url.txt") with open(p, "r", encoding="utf-8") as f: return f.read().strip().rstrip("/") + "/empfang/" except Exception: return _PUBLIC_EMPFANG_URL + "/empfang/" _SETTINGS_FILE = os.path.join(_user_dir(), "empfang_app_settings.json") def _load_settings() -> dict: defaults = {"width": _DEFAULT_W, "height": _DEFAULT_H, "x": None, "y": None, "on_top": False} try: with open(_SETTINGS_FILE, "r", encoding="utf-8") as f: return {**defaults, **json.load(f)} except Exception: return defaults def _save_settings(s: dict): try: with open(_SETTINGS_FILE, "w", encoding="utf-8") as f: json.dump(s, f, indent=2) except Exception: pass class _Api: def __init__(self, window, on_top: bool, url: str): self._w = window self._on_top = on_top self._url = url self._pin_lock = threading.Lock() def check_url(self): """Diagnostic connectivity check (GET with SSL fallback).""" from urllib.request import urlopen, Request for verify in (True, False): try: ctx = ssl.create_default_context() if verify else ssl._create_unverified_context() req = Request(self._url) with urlopen(req, timeout=10, context=ctx) as r: r.read(512) return {"ok": True, "url": self._url, "error": ""} except ssl.SSLError: if verify: continue return {"ok": False, "url": self._url, "error": "SSL/TLS-Zertifikatsfehler. Bitte IT kontaktieren."} except Exception as e: if verify: continue return {"ok": False, "url": self._url, "error": str(e)} return {"ok": False, "url": self._url, "error": "Server nicht erreichbar. Bitte Netzwerk pruefen."} def open_in_browser(self): webbrowser.open(_PUBLIC_EMPFANG_URL) def toggle_on_top(self): if not self._pin_lock.acquire(blocking=False): return self._on_top try: self._on_top = not self._on_top new_val = self._on_top finally: self._pin_lock.release() def _apply(): try: self._w.on_top = new_val except Exception: pass threading.Thread(target=_apply, daemon=True).start() return new_val def get_on_top(self): return self._on_top def get_version(self): try: sys.path.insert(0, _data_dir()) from _build_info import BUILD_TIME, GIT_COMMIT return f"Build: {BUILD_TIME} ({GIT_COMMIT})" except Exception: return "Entwicklungsversion" def get_url(self): return self._url def get_public_url(self): return _PUBLIC_EMPFANG_URL _SHELL_HTML = r'''
AZA Empfang
Empfang wird geladen
Verbindung wird hergestellt…
⚠️
Empfang nicht erreichbar
Die Empfangsseite konnte nicht geladen werden.
''' def main(): try: import webview except ImportError: print("FEHLER: pywebview ist nicht installiert.") print("Bitte ausfuehren: pip install pywebview") sys.exit(1) settings = _load_settings() url = _empfang_url() w = max(_MIN_SIZE[0], min(1920, settings.get("width") or _DEFAULT_W)) h = max(_MIN_SIZE[1], min(1200, settings.get("height") or _DEFAULT_H)) x = settings.get("x") y = settings.get("y") if isinstance(x, (int, float)) and isinstance(y, (int, float)): if x < -200 or y < -200 or x > 3800 or y > 2200: x, y = None, None else: x, y = None, None window = webview.create_window( _APP_TITLE, html=_SHELL_HTML, width=w, height=h, x=x, y=y, min_size=_MIN_SIZE, on_top=settings.get("on_top", False), text_select=True, background_color="#f0f4f8", ) api = _Api(window, settings.get("on_top", False), url) window.expose(api.check_url, api.open_in_browser, api.toggle_on_top, api.get_on_top, api.get_version, api.get_url, api.get_public_url) def _on_closing(): try: _save_settings({ "x": window.x, "y": window.y, "width": window.width, "height": window.height, "on_top": api._on_top, }) except Exception: pass return True try: window.events.closing += _on_closing except Exception: pass try: webview.start() except Exception as e: print(f"[AZA Empfang] Fehler: {e}") if __name__ == "__main__": try: import ctypes ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID( "ch.aza-medwork.empfang.v2") except Exception: pass try: main() except Exception as e: print(f"[AZA Empfang] Kritischer Fehler: {e}") import traceback traceback.print_exc()