mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-18 22:26:30 +01:00
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:
parent
76139c43f6
commit
eec86e099d
4 changed files with 120 additions and 15 deletions
|
@ -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 $@
|
||||||
|
|
||||||
|
|
|
@ -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 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue