7#include <emscripten/html5.h>
16EM_JS(
void, js_create_loading_indicator, (uint32_t
id,
const char* task_name), {
17 if (typeof window.createLoadingIndicator ===
'function') {
18 window.createLoadingIndicator(id, UTF8ToString(task_name));
20 console.warn(
'createLoadingIndicator not defined. Include loading_indicator.js');
24EM_JS(
void, js_update_loading_progress, (uint32_t
id,
float progress,
const char* message), {
25 if (typeof window.updateLoadingProgress ===
'function') {
26 window.updateLoadingProgress(id, progress, UTF8ToString(message));
30EM_JS(
void, js_remove_loading_indicator, (uint32_t
id), {
31 if (typeof window.removeLoadingIndicator ===
'function') {
32 window.removeLoadingIndicator(id);
36EM_JS(
bool, js_check_loading_cancelled, (uint32_t
id), {
37 if (typeof window.isLoadingCancelled ===
'function') {
38 return window.isLoadingCancelled(id);
43EM_JS(
void, js_show_cancel_button, (uint32_t
id), {
44 if (typeof window.showCancelButton ===
'function') {
45 window.showCancelButton(id, function() {});
50WasmLoadingManager& WasmLoadingManager::GetInstance() {
51 static WasmLoadingManager instance;
55WasmLoadingManager::WasmLoadingManager() {}
57WasmLoadingManager::~WasmLoadingManager() {
58 std::lock_guard<std::mutex> lock(mutex_);
59 for (
const auto& [handle, op] : operations_) {
60 if (op && op->active) {
61 js_remove_loading_indicator(GetJsId(handle));
66WasmLoadingManager::LoadingHandle WasmLoadingManager::BeginLoading(
const std::string& task_name) {
67 auto& instance = GetInstance();
70 uint32_t js_id = instance.next_js_id_.fetch_add(1);
71 uint32_t generation = instance.generation_counter_.fetch_add(1);
74 LoadingHandle handle = MakeHandle(js_id, generation);
76 auto operation = std::make_unique<LoadingOperation>();
77 operation->task_name = task_name;
78 operation->active =
true;
79 operation->generation = generation;
82 std::lock_guard<std::mutex> lock(instance.mutex_);
83 instance.operations_[handle] = std::move(operation);
87 js_create_loading_indicator(js_id, task_name.c_str());
88 js_show_cancel_button(js_id);
92void WasmLoadingManager::UpdateProgress(LoadingHandle handle,
float progress) {
93 if (handle == kInvalidHandle)
return;
94 auto& instance = GetInstance();
96 uint32_t js_id = GetJsId(handle);
99 std::lock_guard<std::mutex> lock(instance.mutex_);
100 auto it = instance.operations_.find(handle);
101 if (it == instance.operations_.end() || !it->second->active)
return;
102 it->second->progress = progress;
103 message = it->second->message;
106 js_update_loading_progress(js_id, progress, message.c_str());
109void WasmLoadingManager::UpdateMessage(LoadingHandle handle,
const std::string& message) {
110 if (handle == kInvalidHandle)
return;
111 auto& instance = GetInstance();
112 float progress = 0.0f;
113 uint32_t js_id = GetJsId(handle);
116 std::lock_guard<std::mutex> lock(instance.mutex_);
117 auto it = instance.operations_.find(handle);
118 if (it == instance.operations_.end() || !it->second->active)
return;
119 it->second->message = message;
120 progress = it->second->progress;
123 js_update_loading_progress(js_id, progress, message.c_str());
126bool WasmLoadingManager::IsCancelled(LoadingHandle handle) {
127 if (handle == kInvalidHandle)
return false;
128 auto& instance = GetInstance();
129 uint32_t js_id = GetJsId(handle);
132 bool js_cancelled = js_check_loading_cancelled(js_id);
135 std::lock_guard<std::mutex> lock(instance.mutex_);
136 auto it = instance.operations_.find(handle);
137 if (it == instance.operations_.end() || !it->second->active) {
140 if (js_cancelled && !it->second->cancelled.load()) {
141 it->second->cancelled.store(
true);
143 return it->second->cancelled.load();
147void WasmLoadingManager::EndLoading(LoadingHandle handle) {
148 if (handle == kInvalidHandle)
return;
149 auto& instance = GetInstance();
150 uint32_t js_id = GetJsId(handle);
153 std::lock_guard<std::mutex> lock(instance.mutex_);
154 auto it = instance.operations_.find(handle);
155 if (it != instance.operations_.end()) {
160 it->second->active =
false;
163 if (instance.arena_handle_ == handle) {
164 instance.arena_handle_ = kInvalidHandle;
168 instance.operations_.erase(it);
173 js_remove_loading_indicator(js_id);
176bool WasmLoadingManager::ReportArenaProgress(
int current,
int total,
const std::string& item_name) {
177 auto& instance = GetInstance();
178 LoadingHandle handle;
180 float progress = 0.0f;
181 bool should_update_progress =
false;
182 bool should_update_message =
false;
183 bool is_cancelled =
false;
186 std::lock_guard<std::mutex> lock(instance.mutex_);
187 handle = instance.arena_handle_;
188 if (handle == kInvalidHandle)
return true;
190 js_id = GetJsId(handle);
193 auto it = instance.operations_.find(handle);
194 if (it == instance.operations_.end() || !it->second->active) {
196 instance.arena_handle_ = kInvalidHandle;
202 progress =
static_cast<float>(current) /
static_cast<float>(total);
203 it->second->progress = progress;
204 should_update_progress =
true;
206 progress = it->second->progress;
210 if (!item_name.empty()) {
211 it->second->message = item_name;
212 should_update_message =
true;
216 is_cancelled = it->second->cancelled.load();
220 if (should_update_progress || should_update_message) {
221 js_update_loading_progress(js_id, progress,
222 should_update_message ? item_name.c_str() :
"");
225 return !is_cancelled;
228void WasmLoadingManager::SetArenaHandle(LoadingHandle handle) {
229 auto& instance = GetInstance();
230 std::lock_guard<std::mutex> lock(instance.mutex_);
231 instance.arena_handle_ = handle;
234void WasmLoadingManager::ClearArenaHandle() {
235 auto& instance = GetInstance();
236 std::lock_guard<std::mutex> lock(instance.mutex_);
237 instance.arena_handle_ = kInvalidHandle;
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");} })