Add files via upload

This commit is contained in:
87owo authored and GitHub committed 2026-07-13 19:36:21 +08:00
1 parent 373897f579
commit 802d732b3f
4 files changed
+137 -16

No files matched your search

+32 -3
View File
@@ -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 {
+40 -9
View File
@@ -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) {}
});
});
+11 -1
View File
@@ -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">
+54 -3
View File
@@ -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: