Add files via upload
This commit is contained in:
1 parent
373897f579
commit
802d732b3f
4 files changed
+137
-16
No files matched your search
@@ -648,9 +648,38 @@ select.hidden + .custom-select-wrapper {
|
||||
transition: opacity 0.4s ease, visibility 0.4s ease;
|
||||
}
|
||||
|
||||
#loading_overlay.fade-out {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
#loading_overlay.fade-out {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#loading_overlay.startup-error {
|
||||
padding: 28px;
|
||||
background-color: #f5f5f7;
|
||||
color: #1d1d1f;
|
||||
}
|
||||
|
||||
.startup-error-box {
|
||||
max-width: 520px;
|
||||
padding: 24px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.12);
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.startup-error-box h1 {
|
||||
margin: 0 0 10px;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.startup-error-box p {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
color: #515154;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
|
||||
@@ -59,6 +59,39 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
const getMsg = (key) => (dict[appState.lang] || dict["english_switch"])[key] || key;
|
||||
|
||||
let startupOverlayClosed = false;
|
||||
const closeStartupOverlay = () => {
|
||||
if (startupOverlayClosed) return;
|
||||
startupOverlayClosed = true;
|
||||
|
||||
const overlay = document.getElementById('loading_overlay');
|
||||
if (overlay && !overlay.classList.contains('fade-out')) {
|
||||
overlay.classList.add('fade-out');
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
document.querySelector('.app-container')?.classList.add('fade-in');
|
||||
}, 400);
|
||||
};
|
||||
|
||||
const showStartupError = (message) => {
|
||||
const overlay = document.getElementById('loading_overlay');
|
||||
if (!overlay || startupOverlayClosed) return;
|
||||
|
||||
overlay.classList.add('startup-error');
|
||||
overlay.innerHTML = `
|
||||
<div class="startup-error-box">
|
||||
<h1>PYAS failed to open</h1>
|
||||
<p>${escapeHtml(message)}</p>
|
||||
</div>`;
|
||||
};
|
||||
|
||||
setTimeout(() => {
|
||||
if (!startupOverlayClosed) {
|
||||
closeStartupOverlay();
|
||||
}
|
||||
}, 12000);
|
||||
|
||||
const formatMsg = (key, ...args) => {
|
||||
let msg = getMsg(key);
|
||||
args.forEach((arg, i) => msg = msg.split(`{${i}}`).join(arg));
|
||||
@@ -738,14 +771,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
|
||||
if ((entry.action === 'System' && entry.detail === 'Engine Initialization Complete') || (entry.level === 'WARN' && entry.action === 'init_engine_thread')) {
|
||||
const overlay = document.getElementById('loading_overlay');
|
||||
if (overlay && !overlay.classList.contains('fade-out')) {
|
||||
overlay.classList.add('fade-out');
|
||||
setTimeout(() => {
|
||||
document.querySelector('.app-container')?.classList.add('fade-in');
|
||||
if (window.onEngineReady) window.onEngineReady();
|
||||
}, 400);
|
||||
}
|
||||
closeStartupOverlay();
|
||||
if (window.onEngineReady) window.onEngineReady();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1113,10 +1140,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
});
|
||||
|
||||
closeStartupOverlay();
|
||||
window.pywebview.api.init_ui_ready();
|
||||
}).catch(err => {
|
||||
console.error("Config load failed:", err);
|
||||
window.pywebview.api.init_ui_ready();
|
||||
showStartupError(`Configuration failed to load: ${err?.message || err}`);
|
||||
try {
|
||||
window.pywebview.api.init_ui_ready();
|
||||
} catch (e) {}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -6,7 +6,17 @@
|
||||
<title>PYAS Security</title>
|
||||
<link rel="stylesheet" href="/static/css/style.css">
|
||||
<script defer src="/static/js/i18n.js"></script>
|
||||
<script defer src="/static/js/main.js"></script>
|
||||
<script defer src="/static/js/main.js"></script>
|
||||
<script>
|
||||
window.addEventListener('DOMContentLoaded', function () {
|
||||
window.setTimeout(function () {
|
||||
var app = document.querySelector('.app-container');
|
||||
var overlay = document.getElementById('loading_overlay');
|
||||
if (app) app.classList.add('fade-in');
|
||||
if (overlay && !overlay.classList.contains('fade-out')) overlay.classList.add('fade-out');
|
||||
}, 15000);
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="loading_overlay">
|
||||
|
||||
@@ -87,7 +87,7 @@ class _MainMixin:
|
||||
if not hwnd:
|
||||
return False
|
||||
|
||||
if "-quit" in self.args_pyas or "-driver-unload" in self.args_pyas:
|
||||
if "-quit" in self.args_pyas or "-driver-unload" in self.args_pyas or "-driver-uninstall" in self.args_pyas:
|
||||
return self.send_existing_window_message(hwnd, 3, timeout=1200)
|
||||
|
||||
if "-scan" in self.args_pyas:
|
||||
@@ -1087,6 +1087,33 @@ def get_base_path():
|
||||
|
||||
return os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
def get_frontend_asset_errors():
|
||||
base_path = get_base_path()
|
||||
required_files = [
|
||||
os.path.join("Interface", "templates", "index.html"),
|
||||
os.path.join("Interface", "static", "css", "style.css"),
|
||||
os.path.join("Interface", "static", "js", "i18n.js"),
|
||||
os.path.join("Interface", "static", "js", "main.js"),
|
||||
]
|
||||
errors = []
|
||||
|
||||
for rel_path in required_files:
|
||||
abs_path = os.path.join(base_path, rel_path)
|
||||
if not os.path.isfile(abs_path):
|
||||
errors.append(f"Missing UI asset: {rel_path}")
|
||||
elif os.path.getsize(abs_path) <= 0:
|
||||
errors.append(f"Empty UI asset: {rel_path}")
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
def show_startup_error(message):
|
||||
try:
|
||||
ctypes.windll.user32.MessageBoxW(None, message, PYAS_WINDOW_TITLE, 0x00000010)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
####################################################################################################
|
||||
|
||||
class NoCacheRequestHandler(SimpleHTTPRequestHandler):
|
||||
@@ -1220,9 +1247,22 @@ def start_api(port_container, ready_event):
|
||||
ready_event.set()
|
||||
|
||||
if __name__ == "__main__":
|
||||
if "-driver-unload" in sys.argv:
|
||||
if "-driver-unload" in sys.argv or "-driver-uninstall" in sys.argv:
|
||||
controller = WindowAPI()
|
||||
success = controller.stop_system_driver()
|
||||
if "-driver-uninstall" in sys.argv:
|
||||
deleted, delete_error = False, 0
|
||||
for _ in range(20):
|
||||
deleted, delete_error = controller._delete_driver_service()
|
||||
if deleted:
|
||||
break
|
||||
if delete_error not in (1051, 1072):
|
||||
break
|
||||
time.sleep(0.25)
|
||||
if not deleted:
|
||||
controller.write_log("WARN", "Driver Service", detail=f"DeleteService failed: 0x{delete_error & 0xFFFFFFFF:08X}", success=False)
|
||||
success = (success or not controller.check_system_driver()) and deleted
|
||||
controller.flush_logs_now()
|
||||
os._exit(0 if success or not controller.check_system_driver() else 2)
|
||||
|
||||
hide_on_start = "-h" in sys.argv or "-hide" in sys.argv
|
||||
@@ -1230,6 +1270,11 @@ if __name__ == "__main__":
|
||||
|
||||
os.environ["WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS"] = "--proxy-bypass-list=127.0.0.1,localhost"
|
||||
|
||||
frontend_errors = get_frontend_asset_errors()
|
||||
if frontend_errors:
|
||||
show_startup_error("PYAS UI files are incomplete.\n\n" + "\n".join(frontend_errors))
|
||||
os._exit(4)
|
||||
|
||||
port_container = []
|
||||
server_ready = threading.Event()
|
||||
api_thread = threading.Thread(target=start_api, args=(port_container, server_ready), daemon=True)
|
||||
@@ -1243,8 +1288,9 @@ if __name__ == "__main__":
|
||||
user32 = ctypes.windll.user32
|
||||
pos_x, pos_y = (user32.GetSystemMetrics(0) - init_width) // 2, (user32.GetSystemMetrics(1) - init_height) // 2
|
||||
|
||||
startup_url = f"http://127.0.0.1:{port_container[0]}/"
|
||||
window = webview.create_window(
|
||||
title=PYAS_WINDOW_TITLE, url=f"http://127.0.0.1:{port_container[0]}/", width=init_width, height=init_height, x=pos_x, y=pos_y,
|
||||
title=PYAS_WINDOW_TITLE, url=startup_url, width=init_width, height=init_height, x=pos_x, y=pos_y,
|
||||
frameless=True, easy_drag=False, js_api=js_api, background_color='#e0e0e0', hidden=hide_on_start)
|
||||
|
||||
if platform.system() == "Windows":
|
||||
@@ -1268,6 +1314,11 @@ if __name__ == "__main__":
|
||||
|
||||
def webview_startup_watchdog():
|
||||
if not hide_on_start and not webview_ready_event.wait(60.0):
|
||||
try:
|
||||
webbrowser.open(startup_url)
|
||||
except Exception:
|
||||
pass
|
||||
show_startup_error("PYAS WebView did not finish loading. The app was opened in your default browser as a fallback.")
|
||||
try:
|
||||
js_api.flush_logs_now()
|
||||
except Exception:
|
||||
|
||||
Reference in new issue
Block a user