7#include <emscripten/html5.h>
15std::atomic<bool> WasmErrorHandler::initialized_{
false};
16std::atomic<int> WasmErrorHandler::callback_counter_{0};
20 std::function<void(
bool)> callback;
23static std::map<int, CallbackEntry> g_confirm_callbacks;
24static std::mutex g_callback_mutex;
27constexpr double kCallbackTimeoutMs = 5.0 * 60.0 * 1000.0;
31 return EM_ASM_DOUBLE({
return Date.now(); });
35static void CleanupStaleCallbacks() {
36 std::lock_guard<std::mutex> lock(g_callback_mutex);
39 for (
auto it = g_confirm_callbacks.begin(); it != g_confirm_callbacks.end();) {
40 if (now - it->second.timestamp > kCallbackTimeoutMs) {
41 it = g_confirm_callbacks.erase(it);
49EM_JS(
void, js_register_cleanup_handler, (), {
50 window.addEventListener(
'beforeunload', function() {
52 if (Module._cleanupConfirmCallbacks) {
53 Module._cleanupConfirmCallbacks();
59extern "C" EMSCRIPTEN_KEEPALIVE
void cleanupConfirmCallbacks() {
60 std::lock_guard<std::mutex> lock(g_callback_mutex);
61 g_confirm_callbacks.clear();
65EM_JS(
void, js_show_modal, (
const char* title,
const char* message,
const char* type), {
66 var titleStr = UTF8ToString(title);
67 var messageStr = UTF8ToString(message);
68 var typeStr = UTF8ToString(type);
69 if (typeof window.showYazeModal ===
'function') {
70 window.showYazeModal(titleStr, messageStr, typeStr);
72 alert(titleStr +
'\n\n' + messageStr);
76EM_JS(
void, js_show_toast, (
const char* message,
const char* type,
int duration_ms), {
77 var messageStr = UTF8ToString(message);
78 var typeStr = UTF8ToString(type);
79 if (typeof window.showYazeToast ===
'function') {
80 window.showYazeToast(messageStr, typeStr, duration_ms);
82 console.log(
'[' + typeStr +
'] ' + messageStr);
86EM_JS(
void, js_show_progress, (
const char* task,
float progress), {
87 var taskStr = UTF8ToString(task);
88 if (typeof window.showYazeProgress ===
'function') {
89 window.showYazeProgress(taskStr, progress);
91 console.log(
'Progress: ' + taskStr +
' - ' + (progress * 100).toFixed(0) +
'%');
95EM_JS(
void, js_hide_progress, (), {
96 if (typeof window.hideYazeProgress ===
'function') {
97 window.hideYazeProgress();
101EM_JS(
void, js_show_confirm, (
const char* message,
int callback_id), {
102 var messageStr = UTF8ToString(message);
103 if (typeof window.showYazeConfirm ===
'function') {
104 window.showYazeConfirm(messageStr, function(result) {
105 Module._handleConfirmCallback(callback_id, result ? 1 : 0);
108 var result = confirm(messageStr);
109 Module._handleConfirmCallback(callback_id, result ? 1 : 0);
113EM_JS(
void, js_inject_styles, (), {
114 if (document.getElementById(
'yaze-error-handler-styles')) {
117 var link = document.createElement(
'link');
118 link.id =
'yaze-error-handler-styles';
119 link.rel =
'stylesheet';
120 link.href =
'error_handler.css';
121 link.onerror = function() {
122 var style = document.createElement(
'style');
123 style.textContent =
'.yaze-modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.5);display:flex;align-items:center;justify-content:center;z-index:10000}.yaze-modal-content{background:white;border-radius:8px;padding:24px;max-width:500px;box-shadow:0 4px 6px rgba(0,0,0,0.1)}.yaze-toast{position:fixed;bottom:20px;right:20px;padding:12px 20px;border-radius:4px;color:white;z-index:10001}.yaze-toast-info{background:#3498db}.yaze-toast-success{background:#2ecc71}.yaze-toast-warning{background:#f39c12}.yaze-toast-error{background:#e74c3c}';
124 document.head.appendChild(style);
126 document.head.appendChild(link);
130extern "C" EMSCRIPTEN_KEEPALIVE
void handleConfirmCallback(
int callback_id,
int result) {
131 std::function<void(
bool)> callback;
133 std::lock_guard<std::mutex> lock(g_callback_mutex);
134 auto it = g_confirm_callbacks.find(callback_id);
135 if (it != g_confirm_callbacks.end()) {
136 callback = it->second.callback;
137 g_confirm_callbacks.erase(it);
141 callback(result != 0);
145void WasmErrorHandler::Initialize() {
147 bool expected =
false;
148 if (!initialized_.compare_exchange_strong(expected,
true)) {
153 Module._handleConfirmCallback = Module.cwrap(
'handleConfirmCallback', null, [
'number',
'number']);
154 Module._cleanupConfirmCallbacks = Module.cwrap(
'cleanupConfirmCallbacks', null, []);
156 js_register_cleanup_handler();
159void WasmErrorHandler::ShowError(
const std::string& title,
const std::string& message) {
160 if (!initialized_.load()) Initialize();
161 js_show_modal(title.c_str(), message.c_str(),
"error");
164void WasmErrorHandler::ShowWarning(
const std::string& title,
const std::string& message) {
165 if (!initialized_.load()) Initialize();
166 js_show_modal(title.c_str(), message.c_str(),
"warning");
169void WasmErrorHandler::ShowInfo(
const std::string& title,
const std::string& message) {
170 if (!initialized_.load()) Initialize();
171 js_show_modal(title.c_str(), message.c_str(),
"info");
174void WasmErrorHandler::Toast(
const std::string& message, ToastType type,
int duration_ms) {
175 if (!initialized_.load()) Initialize();
176 const char* type_str =
"info";
178 case ToastType::kSuccess: type_str =
"success";
break;
179 case ToastType::kWarning: type_str =
"warning";
break;
180 case ToastType::kError: type_str =
"error";
break;
181 case ToastType::kInfo:
182 default: type_str =
"info";
break;
184 js_show_toast(message.c_str(), type_str, duration_ms);
187void WasmErrorHandler::ShowProgress(
const std::string& task,
float progress) {
188 if (!initialized_.load()) Initialize();
189 if (progress < 0.0f) progress = 0.0f;
190 if (progress > 1.0f) progress = 1.0f;
191 js_show_progress(task.c_str(), progress);
194void WasmErrorHandler::HideProgress() {
195 if (!initialized_.load()) Initialize();
199void WasmErrorHandler::Confirm(
const std::string& message, std::function<
void(
bool)> callback) {
200 if (!initialized_.load()) Initialize();
203 CleanupStaleCallbacks();
205 int callback_id = callback_counter_.fetch_add(1) + 1;
207 std::lock_guard<std::mutex> lock(g_callback_mutex);
208 g_confirm_callbacks[callback_id] = CallbackEntry{callback,
GetCurrentTimeMs()};
210 js_show_confirm(message.c_str(), callback_id);
uint64_t GetCurrentTimeMs()
EM_JS(void, CallJsAiDriver,(const char *history_json), { if(window.yaze &&window.yaze.ai &&window.yaze.ai.processAgentRequest) { window.yaze.ai.processAgentRequest(UTF8ToString(history_json));} else { console.error("AI Driver not found in window.yaze.ai.processAgentRequest");} })