make alert and confirm non-blocking

Using a custom div and callbacks. TODO: make it floating so it's more
dialog-like. But that's just css at this point.
This commit is contained in:
Eric House 2021-02-13 10:37:47 -08:00
parent 76139c43f6
commit eec86e099d
4 changed files with 120 additions and 15 deletions

View file

@ -72,7 +72,7 @@ main.html: ${INPUTS} $(MAKEFILE) shell_minimal.html
--preload-file assets_dir --shell-file shell_minimal.html \ --preload-file assets_dir --shell-file shell_minimal.html \
-s USE_SDL_TTF=2 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS='["png"]' \ -s USE_SDL_TTF=2 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS='["png"]' \
-s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall']" \ -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall']" \
-s EXPORTED_FUNCTIONS='["_main", "_button", "_newgame", "_gotMQTTMsg", "_jscallback"]' \ -s EXPORTED_FUNCTIONS='["_main", "_button", "_newgame", "_gotMQTTMsg", "_jscallback", "_onDlgButton"]' \
-s WASM=1 \ -s WASM=1 \
${INPUTS} -o $@ ${INPUTS} -o $@

View file

@ -54,12 +54,30 @@
#define KEY_GAME "the_game" #define KEY_GAME "the_game"
#define DICTNAME "assets_dir/CollegeEng_2to8.xwd" #define DICTNAME "assets_dir/CollegeEng_2to8.xwd"
EM_JS(bool, call_confirm, (const char* str), { #define BUTTON_OK "OK"
return confirm(UTF8ToString(str)); #define BUTTON_CANCEL "Cancel"
});
EM_JS(void, call_alert, (const char* str), { typedef void (*AlertProc)(void* closure, const char* button);
alert(UTF8ToString(str));
}); /* typedef struct _Buttons { */
/* int nButtons; */
/* const char** buttons; */
/* } Buttons; */
EM_JS(void, call_dialog, (const char* str, const char** but_strs,
AlertProc proc, void* closure), {
var buttons = [];
for ( let ii = 0; ii < 3; ++ii ) {
const mem = HEAP32[(but_strs + (ii * 4)) >> 2];
if ( 0 == mem ) {
break;
}
const str = UTF8ToString(mem);
buttons.push(str);
}
nbDialog(UTF8ToString(str), buttons, proc, closure);
} );
EM_JS(void, call_haveDevID, (void* closure, const char* devid), { EM_JS(void, call_haveDevID, (void* closure, const char* devid), {
onHaveDevID(closure, UTF8ToString(devid)); onHaveDevID(closure, UTF8ToString(devid));
}); });
@ -87,6 +105,13 @@ EM_JS(void, setButtonText, (const char* id, const char* text), {
static void updateScreen( Globals* globals, bool doSave ); static void updateScreen( Globals* globals, bool doSave );
static void
call_alert( const char* msg )
{
const char* buttons[] = { BUTTON_OK, NULL };
call_dialog( msg, buttons, NULL, NULL );
}
static XP_S16 static XP_S16
send_msg( XWEnv xwe, const XP_U8* buf, XP_U16 len, send_msg( XWEnv xwe, const XP_U8* buf, XP_U16 len,
const XP_UCHAR* msgNo, const CommsAddrRec* addr, const XP_UCHAR* msgNo, const CommsAddrRec* addr,
@ -203,8 +228,9 @@ gameFromInvite( Globals* globals, const NetLaunchInfo* invite )
if ( globals->gi.gameID == invite->gameID ) { if ( globals->gi.gameID == invite->gameID ) {
XP_LOGFF( "duplicate invite; ignoring" ); XP_LOGFF( "duplicate invite; ignoring" );
needsLoad = false; needsLoad = false;
} else if ( ! call_confirm( "Invitation received; replace current game?" ) ) { } else {
needsLoad = false; call_alert( "Invitation received; replace current game?" );
// needsLoad = false;
} }
} else if ( invite->lang != 1 ) { } else if ( invite->lang != 1 ) {
call_alert( "Invitations are only supported for play in English right now." ); call_alert( "Invitations are only supported for play in English right now." );
@ -425,12 +451,32 @@ main_set_timer( Globals* globals, XWTimerReason why, XP_U16 when,
jscallback_set( onTimerFired, tc, when ); jscallback_set( onTimerFired, tc, when );
} }
typedef struct _QueryState {
Globals* globals;
QueryProc proc;
void* closure;
} QueryState;
static void
onQueryCalled( void* closure, const char* button )
{
QueryState* qs = (QueryState*)closure;
bool ok = 0 == strcmp( button, BUTTON_OK );
(*qs->proc)( qs->closure, ok );
updateTradeButton( qs->globals );
XP_FREE( qs->globals->mpool, qs );
}
void void
main_query( Globals* globals, const XP_UCHAR* query, QueryProc proc, void* closure ) main_query( Globals* globals, const XP_UCHAR* query, QueryProc proc, void* closure )
{ {
bool ok = call_confirm( query ); QueryState* qs = XP_MALLOC( globals->mpool, sizeof(*qs) );
(*proc)( closure, ok ); qs->proc = proc;
updateTradeButton( globals ); qs->closure = closure;
qs->globals = globals;
const char* buttons[] = { BUTTON_CANCEL, BUTTON_OK, NULL };
call_dialog( query, buttons, onQueryCalled, qs );
} }
void void
@ -668,14 +714,35 @@ initNoReturn( int argc, const char** argv )
emscripten_set_main_loop_arg( looper, globals, -1, 1 ); emscripten_set_main_loop_arg( looper, globals, -1, 1 );
} }
typedef struct _NewgameState {
Globals* globals;
bool p0;
bool p1;
} NewgameState;
static void
onNewgameResponse( void* closure, const char* button )
{
NewgameState* ngs = (NewgameState*)closure;
Globals* globals = ngs->globals;
if ( 0 == strcmp( button, BUTTON_OK ) ) {
loadAndDraw( ngs->globals, NULL, true, ngs->p0, ngs->p1 );
}
XP_FREE( globals->mpool, ngs );
}
void void
newgame( void* closure, bool p0, bool p1 ) newgame( void* closure, bool p0, bool p1 )
{ {
Globals* globals = (Globals*)closure; Globals* globals = (Globals*)closure;
NewgameState* ngs = XP_MALLOC( globals->mpool, sizeof(*ngs) );
ngs->globals = globals;
ngs->p0 = p0;
ngs->p1 = p1;
XP_LOGFF( "(args: %d,%d)", p0, p1 ); XP_LOGFF( "(args: %d,%d)", p0, p1 );
if ( call_confirm("Are you sure you want to replace the current game?") ) { const char* query = "Are you sure you want to replace the current game?";
loadAndDraw( globals, NULL, true, p0, p1 ); const char* buttons[] = { BUTTON_CANCEL, BUTTON_OK, NULL };
} call_dialog( query, buttons, onNewgameResponse, ngs );
} }
void void
@ -692,6 +759,14 @@ jscallback( JSCallback proc, void* closure )
(*proc)(closure); (*proc)(closure);
} }
void
onDlgButton( AlertProc proc, void* closure, const char* button )
{
if ( !!proc ) {
(*proc)( closure, button );
}
}
int int
main( int argc, const char** argv ) main( int argc, const char** argv )
{ {

View file

@ -45,6 +45,9 @@
to {transform: rotate(360deg);} to {transform: rotate(360deg);}
} }
#nbalert {
}
</style> </style>
</head> </head>
<body class="centered"> <body class="centered">
@ -54,6 +57,7 @@
<div class="emscripten"> <div class="emscripten">
<progress value="0" max="100" id="progress" hidden=1></progress> <progress value="0" max="100" id="progress" hidden=1></progress>
</div> </div>
<div id='nbalert'></div>
<div class="emscripten_border"> <div class="emscripten_border">
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas> <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>
</div> </div>

View file

@ -75,6 +75,32 @@ function mqttSend( topic, ptr ) {
return canSend; return canSend;
} }
function nbDialog(msg, buttons, proc, closure) {
let dlg = document.getElementById('nbalert');
while (dlg.firstChild) {
dlg.removeChild(dlg.firstChild);
}
let txtDiv = document.createElement('div');
txtDiv.textContent = msg
dlg.appendChild( txtDiv );
let span = document.createElement('div');
for ( let buttonTxt of buttons ) {
let button = document.createElement('button');
button.textContent = buttonTxt;
button.onclick = function() {
Module.ccall('onDlgButton', null, ['number', 'number', 'string'],
[proc, closure, buttonTxt]);
dlg.style.display = 'none'; // hide
};
span.appendChild( button );
}
dlg.appendChild( span );
dlg.style.display = 'block'; // reveal
}
for ( let one of ['paho-mqtt.js'] ) { for ( let one of ['paho-mqtt.js'] ) {
let script = document.createElement('script'); let script = document.createElement('script');
script.src = one script.src = one