mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-01 06:19:57 +01:00
use notifications and other tweaks
This commit is contained in:
parent
0d7b81ac72
commit
585f55c040
8 changed files with 80 additions and 24 deletions
|
@ -884,11 +884,13 @@ board_canHint( const BoardCtxt* board )
|
|||
return canHint;
|
||||
}
|
||||
|
||||
#ifdef XWFEATURE_CHAT
|
||||
void
|
||||
board_sendChat( const BoardCtxt* board, XWEnv xwe, const XP_UCHAR* msg )
|
||||
{
|
||||
server_sendChat( board->server, xwe, msg, board->selPlayer );
|
||||
}
|
||||
#endif
|
||||
|
||||
static XP_U16
|
||||
adjustOffset( XP_U16 curOffset, XP_S16 zoomBy )
|
||||
|
|
|
@ -553,6 +553,8 @@ game_summarize( XWGame* game, CurGameInfo* gi, GameSummary* summary )
|
|||
summary->turn = server_getCurrentTurn( server, &summary->turnIsLocal );
|
||||
summary->lastMoveTime = server_getLastMoveTime(server);
|
||||
summary->lang = gi->dictLang;
|
||||
summary->gameOver = server_getGameIsOver( server );
|
||||
|
||||
for ( int ii = 0; ii < gi->nPlayers; ++ii ) {
|
||||
LocalPlayer* lp = &gi->players[ii];
|
||||
if ( LP_IS_ROBOT(lp) || !LP_IS_LOCAL(lp) ) {
|
||||
|
|
|
@ -53,7 +53,7 @@ typedef struct _GameStateInfo {
|
|||
|
||||
typedef struct _GameSummary {
|
||||
XP_Bool turnIsLocal;
|
||||
XP_Bool inPlay;
|
||||
XP_Bool gameOver;
|
||||
XP_S8 turn;
|
||||
XP_U32 lastMoveTime;
|
||||
XP_U8 missingPlayers;
|
||||
|
|
|
@ -22,7 +22,6 @@ DEBS = cmake
|
|||
|
||||
INPUTS = main.c wasmdict.c wasmutls.c wasmdraw.c wasmutil.c wasmdutil.c ${COMMONSRC}
|
||||
|
||||
DEFINES += -DXWFEATURE_CHAT
|
||||
DEFINES += -DXWFEATURE_BONUSALL
|
||||
DEFINES += -DMAX_ROWS=32
|
||||
DEFINES += -DCOMMON_LAYOUT
|
||||
|
|
|
@ -95,9 +95,10 @@
|
|||
// #define GLOBALS_ON_STACK
|
||||
|
||||
typedef struct _NewGameParams {
|
||||
Globals* globals;
|
||||
bool isRobotNotRemote;
|
||||
bool hintsNotAllowed;
|
||||
const char* lc;
|
||||
char lc[8];
|
||||
} NewGameParams;
|
||||
|
||||
static void updateScreen( GameState* gs, bool doSave );
|
||||
|
@ -248,6 +249,22 @@ EM_JS(void, js_callNewGame, (const char* msg, void* closure,
|
|||
nbGetNewGame(closure, jsmsg, jlangs);
|
||||
});
|
||||
|
||||
EM_JS(bool, js_getHaveNotifyPerm, (), {
|
||||
let perm = Notification.permission;
|
||||
return perm == 'granted';
|
||||
});
|
||||
|
||||
EM_JS(void, js_requestNotify, (), {
|
||||
Notification.requestPermission();
|
||||
});
|
||||
|
||||
EM_JS( void, js_notify, (const char* msg), {
|
||||
const jsmsg = UTF8ToString(msg);
|
||||
new Notification('WASM CrossWords',
|
||||
{ body: jsmsg, renotify: true, }
|
||||
);
|
||||
});
|
||||
|
||||
typedef struct _ConfirmState {
|
||||
Globals* globals;
|
||||
BoolProc proc;
|
||||
|
@ -585,10 +602,10 @@ formatForGame(Globals* globals, bool multiLangs, const XP_UCHAR* gameKey )
|
|||
offset += snprintf( buf+offset, sizeof(buf)-offset, " (in %s)", langName );
|
||||
}
|
||||
}
|
||||
offset += snprintf( buf+offset, sizeof(buf)-offset, " My turn: %s",
|
||||
summary.turnIsLocal ? "YES" : "NO" );
|
||||
offset += snprintf( buf+offset, sizeof(buf)-offset, " Opponent: %s",
|
||||
summary.opponents );
|
||||
offset += snprintf( buf+offset, sizeof(buf)-offset, " My turn: %s",
|
||||
0 <= summary.turn && summary.turnIsLocal ? "YES" : "NO" );
|
||||
}
|
||||
char* result = NULL;
|
||||
replaceStringIfDifferent( globals->mpool, &result, buf );
|
||||
|
@ -847,16 +864,17 @@ onConflict( void* closure, const char* ignored )
|
|||
}
|
||||
|
||||
static void
|
||||
onFocussed( void* closure, const char* ignored )
|
||||
onFocussed( void* closure, const char* newState )
|
||||
{
|
||||
XP_LOGFF("Need to refresh...");
|
||||
CAST_GLOB(Globals*, globals, closure);
|
||||
globals->focussed = 0 == strcmp("focus", newState);
|
||||
XP_LOGFF( "focussed now: %d", globals->focussed );
|
||||
/* This hasn't worked.... */
|
||||
/* CAST_GLOB(Globals*, globals, closure); */
|
||||
/* GameState* gs = getCurGame( globals ); */
|
||||
/* if ( !!gs ) { */
|
||||
/* board_invalAll( gs->game.board ); */
|
||||
/* updateScreen( gs, false ); */
|
||||
/* } */
|
||||
GameState* gs = getCurGame( globals );
|
||||
if ( !!gs ) {
|
||||
board_invalAll( gs->game.board );
|
||||
updateScreen( gs, false );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1327,8 +1345,10 @@ loadAndDraw( Globals* globals, const NetLaunchInfo* invite,
|
|||
gs->gi.players[0].isLocal = XP_TRUE;
|
||||
gs->gi.players[0].robotIQ = 0;
|
||||
|
||||
gs->gi.players[1].name = copyString( globals->mpool, "Robot" );
|
||||
gs->gi.players[1].isLocal = !!params ? params->isRobotNotRemote : true;
|
||||
bool otherLocal = !!params ? params->isRobotNotRemote : true;
|
||||
gs->gi.players[1].name = copyString( globals->mpool,
|
||||
otherLocal ? "Robot" : "(remote)" );
|
||||
gs->gi.players[1].isLocal = otherLocal;
|
||||
XP_LOGFF( "set isLocal[1]: %d", gs->gi.players[1].isLocal );
|
||||
gs->gi.players[1].robotIQ = 99; /* doesn't matter if remote */
|
||||
|
||||
|
@ -1387,6 +1407,15 @@ main_onGameMessage( Globals* globals, XP_U32 gameID,
|
|||
if ( game_receiveMessage( &gs->game, NULL, stream, from ) ) {
|
||||
updateScreen( gs, true );
|
||||
}
|
||||
if ( !globals->focussed && js_getHaveNotifyPerm() ) {
|
||||
GameSummary summary;
|
||||
game_summarize( &gs->game, &gs->gi, &summary );
|
||||
if ( summary.turnIsLocal ) {
|
||||
char buf[128];
|
||||
sprintf( buf, "Your turn in game %s", gs->gameName );
|
||||
js_notify( buf );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
char msg[128];
|
||||
snprintf( msg, sizeof(msg), "Dropping move for deleted game (id: %X/%d)",
|
||||
|
@ -1473,7 +1502,7 @@ main_turnChanged( GameState* gs, int newTurn )
|
|||
if ( 0 <= newTurn && !isVisible(gs) && gs->gi.players[newTurn].isLocal ) {
|
||||
char msg[128];
|
||||
snprintf( msg, sizeof(msg),
|
||||
"It's your turn in background game \"%s\". Would you like to open it now?",
|
||||
"It's your turn in game \"%s\". Would you like to open it now?",
|
||||
gs->gameName );
|
||||
call_confirm( gs->globals, msg, openConfirmed, gs );
|
||||
}
|
||||
|
@ -1850,20 +1879,37 @@ cbckBinary( BinProc proc, void* closure, int len, const uint8_t* msg )
|
|||
(*proc)(closure, msg, len );
|
||||
}
|
||||
|
||||
static void
|
||||
onAllowNotify(void* closure, bool confirmed)
|
||||
{
|
||||
NewGameParams* ngp = (NewGameParams*)closure;
|
||||
Globals* globals = ngp->globals;
|
||||
if ( confirmed ) {
|
||||
js_requestNotify();
|
||||
}
|
||||
loadAndDraw( globals, NULL, 0, ngp );
|
||||
updateDeviceButtons( globals );
|
||||
XP_FREE( globals->mpool, ngp );
|
||||
}
|
||||
|
||||
void
|
||||
onNewGame( void* closure, bool opponentIsRobot, const char* langName )
|
||||
{
|
||||
Globals* globals = (Globals*)closure;
|
||||
XP_LOGFF( "isRobot: %d; lc: %s", opponentIsRobot, langName );
|
||||
|
||||
char lc[8];
|
||||
langNameToLC(globals, langName, lc, sizeof(lc));
|
||||
NewGameParams* ngp = XP_CALLOC( globals->mpool, sizeof(*ngp) );
|
||||
ngp->globals = globals;
|
||||
ngp->isRobotNotRemote = opponentIsRobot;
|
||||
langNameToLC(globals, langName, ngp->lc, sizeof(ngp->lc));
|
||||
|
||||
NewGameParams ngp = { .isRobotNotRemote = opponentIsRobot,
|
||||
.lc = lc,
|
||||
};
|
||||
loadAndDraw( globals, NULL, 0, &ngp );
|
||||
updateDeviceButtons( globals );
|
||||
if ( !opponentIsRobot && !js_getHaveNotifyPerm() ) {
|
||||
const char* msg = "You are creating a networked game. Would you like "
|
||||
"notifications when a move arrives and it becomes your turn?";
|
||||
call_confirm( globals, msg, onAllowNotify, ngp );
|
||||
} else {
|
||||
onAllowNotify(ngp, false);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called from js with a proc and closure */
|
||||
|
|
|
@ -67,6 +67,8 @@ typedef struct Globals {
|
|||
CommonPrefs cp;
|
||||
DictMgrCtxt* dictMgr;
|
||||
|
||||
bool focussed; /* window is in foreground */
|
||||
|
||||
char playerName[32];
|
||||
|
||||
#ifdef MEM_DEBUG
|
||||
|
|
|
@ -590,7 +590,9 @@ wasm_util_make( MPFORMAL CurGameInfo* gi, XW_DUtilCtxt* dctxt, GameState* closur
|
|||
SET_VTABLE_ENTRY( wuctxt->super.vtable, util_informMissing, wasm );
|
||||
SET_VTABLE_ENTRY( wuctxt->super.vtable, util_addrChange, wasm );
|
||||
SET_VTABLE_ENTRY( wuctxt->super.vtable, util_informWordsBlocked, wasm );
|
||||
#ifdef XWFEATURE_CHAT
|
||||
SET_VTABLE_ENTRY( wuctxt->super.vtable, util_showChat, wasm );
|
||||
#endif
|
||||
SET_VTABLE_ENTRY( wuctxt->super.vtable, util_getDevUtilCtxt, wasm );
|
||||
|
||||
size_t sizeInBytes = sizeof(*wuctxt->super.vtable);
|
||||
|
|
|
@ -131,7 +131,10 @@ function jssetup(closure, dbg, devid, gitrev, now, noTabProc, focusProc, msgProc
|
|||
window.addEventListener('storage', listener);
|
||||
|
||||
window.onfocus = function () {
|
||||
ccallString(focusProc, state.closure, '');
|
||||
ccallString(focusProc, state.closure, 'focus');
|
||||
};
|
||||
window.onblur = function () {
|
||||
ccallString(focusProc, state.closure, 'blur');
|
||||
};
|
||||
|
||||
state.closure = closure;
|
||||
|
|
Loading…
Reference in a new issue