mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-09-14 15:16:40 +00:00
feat(sim): board feature parity (reset/GPS/sensors/admin/keyboard) + input fixes
Rounds out the browser sim harness with the rest of the physical board's interactions: a reset button (JS-driven, since board.reboot() is inert under -sEXIT_RUNTIME=0), GPS input wired into a real LocationProvider via new SimSensorManager, JS-settable battery/environment telemetry, an admin/repeater-login test hook (sendRoomLogin against the default "password"), and full physical-keyboard text entry (printable ASCII passthrough into the existing KeyboardWidget, Tab->KEY_KB_ENTER submit). Also fixes three real bugs found while exercising all of this in a real browser: - UITask.cpp's native-only stdin poll branch had no __EMSCRIPTEN__ exclusion, so it also compiled into the wasm build and called a real, blocking window.prompt() on nearly every frame -- the actual cause of the reported time/controls jumping. Now gated to native only. - 'n'/'p' were mapped as Next/Prev keyboard shortcuts, colliding with typing those literal letters. Removed the shortcuts; added explicit Next/Prev buttons to mesh.html (previously relied solely on them). - Buttons grabbed native browser keyboard focus on click, so a later stray Enter/Space could silently re-trigger a previously-clicked button (e.g. Reset). mousedown now calls preventDefault() on all buttons. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -422,4 +422,54 @@ extern "C" EMSCRIPTEN_KEEPALIVE int sim_test_open_dm_with_first_contact() {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Same idea as findFirstChatContact() above, but for the first known
|
||||
// admin-loginable contact (a repeater or room server) instead of another
|
||||
// chat instance.
|
||||
static bool findFirstAdminContact(ContactInfo& out) {
|
||||
int n = the_mesh.getNumContacts();
|
||||
for (int i = 0; i < n; i++) {
|
||||
ContactInfo ci;
|
||||
if (the_mesh.getContactByIdx(MAX_ANON_CONTACTS + i, ci) &&
|
||||
(ci.type == ADV_TYPE_REPEATER || ci.type == ADV_TYPE_ROOM)) {
|
||||
out = ci;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
// Jumps the on-device UI straight to AdminScreen for the first known
|
||||
// repeater/room contact -- UITask::openAdminFor(ci, false), the exact same
|
||||
// function NearbyScreen's "Nodes" Hold-Enter admin action calls (see
|
||||
// NearbyScreen.h:709), so a test harness can screenshot the real Admin
|
||||
// screen instead of scripting contact-list navigation key-by-key. Returns
|
||||
// 1 if a repeater/room contact was found and the screen switched, 0 if not.
|
||||
extern "C" EMSCRIPTEN_KEEPALIVE int sim_test_open_admin_with_first_repeater() {
|
||||
if (!g_sim_ready) return 0;
|
||||
ContactInfo ci;
|
||||
if (!findFirstAdminContact(ci)) return 0;
|
||||
ui_task.openAdminFor(ci, false);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Submits a login against the first known repeater/room contact via
|
||||
// MyMesh::sendRoomLogin() -- the exact same function AdminScreen's own
|
||||
// submit button calls (examples/companion_radio/ui-new/AdminScreen.h) --
|
||||
// so a test harness can verify the admin/password flow without scripting
|
||||
// the on-device virtual keyboard. Only reports whether the login *request*
|
||||
// was sent (matching sim_test_send_msg_to_first_contact()'s same
|
||||
// synchronous-only contract) -- the actual accept/reject arrives async via
|
||||
// AbstractUITask::onRoomLoginResult() and is visible on AdminScreen once
|
||||
// sim_test_open_admin_with_first_repeater() has switched to it. Returns 1
|
||||
// if sent, 0 if send failed, -1 if no repeater/room contact known yet.
|
||||
extern "C" EMSCRIPTEN_KEEPALIVE int sim_test_login_first_repeater(const char* password) {
|
||||
if (!g_sim_ready) return -1;
|
||||
ContactInfo ci;
|
||||
if (!findFirstAdminContact(ci)) return -1;
|
||||
uint32_t est_timeout;
|
||||
return the_mesh.sendRoomLogin(ci, password, est_timeout) ? 1 : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2424,7 +2424,21 @@ void UITask::loop() {
|
||||
} else if (ev == BUTTON_EVENT_TRIPLE_CLICK) {
|
||||
if (!_locked) enqueueKey(handleTripleClick(KEY_SELECT));
|
||||
}
|
||||
#elif defined(SIM_PLATFORM)
|
||||
#elif defined(SIM_PLATFORM) && !defined(__EMSCRIPTEN__)
|
||||
// Native terminal input ONLY -- this branch previously had no
|
||||
// __EMSCRIPTEN__ exclusion, so it also compiled into the wasm build
|
||||
// (SIM_PLATFORM is defined there too, and UI_HAS_JOYSTICK/PIN_USER_BTN
|
||||
// are both unset for variants/sim). Every tick it called real select()/
|
||||
// read() on fd 0; under Emscripten, with no stdin ever wired up, that
|
||||
// hits the runtime's default TTY device, which falls back to a real,
|
||||
// blocking window.prompt("Input: ") -- so every single browser tab
|
||||
// running the wasm build was popping a native dialog on nearly every
|
||||
// frame, discovered by seeing Playwright's page 'dialog' event fire
|
||||
// continuously from the moment the module boots. The wasm build's own
|
||||
// input already comes through sim_enqueue_key()/injectSimKey() (see
|
||||
// above, in the #if defined(SIM_PLATFORM) && defined(__EMSCRIPTEN__)
|
||||
// block) -- this stdin-poll branch was only ever meant for Phase 1's
|
||||
// native terminal target.
|
||||
// Native terminal input: stdin is put into raw/non-canonical mode by
|
||||
// variants/sim/sim_main.cpp's main(), so keys arrive here one at a time
|
||||
// with no Enter-to-submit line buffering. Non-blocking select() on fd 0
|
||||
|
||||
Reference in New Issue
Block a user