add notifications for games which are not currently visible

This commit is contained in:
Jesse D. McDonald 2020-05-09 12:54:49 -05:00
parent a523c81f88
commit 8621724c40
1 changed files with 95 additions and 70 deletions

View File

@ -169,7 +169,7 @@ $(function (){
animate = false;
}
$('#cb_board').data('last_state', currentGame.moves);
notifyLocalMove(currentGame, $('#cb_board').data('gameId'));
setCurrentGame(currentGame, animate);
putState();
}
@ -404,28 +404,8 @@ $(function (){
}
function setCurrentGame(game, animate) {
closeNotifications();
currentGame = game;
setVisibleGame(game, animate);
const moves = game.moves;
const cb_board = $('#cb_board').first();
if (!deepEqual(moves, cb_board.data('last_state'))) {
/* ignore partial moves */
if (!game.board.phantom) {
if ($('#cb_notify')[0].checked) {
const gameString = cb_board.data('lightName') + ' vs. ' + cb_board.data('darkName');
notify(gameString + '\n' + $('#cb_message').text());
}
if ($('#cb_sound')[0].checked) {
playNotifySound();
}
}
}
cb_board.data('last_state', moves);
}
function randomId(){
@ -588,7 +568,7 @@ $(function (){
function putState() {
const boardElem = $('#cb_board');
const gameId = boardElem.data('gameId');
boardElem.data('last_state', currentGame.moves);
notifyLocalMove(currentGame, boardElem.data('gameId'));
putMeta({ board: JSON.parse(currentGame.toJSON()) });
}
@ -640,18 +620,9 @@ $(function (){
boardElem.data('modified', 0);
history.replaceState(null, document.title, '#/' + newId);
const notifyAfter = +new Date() + 2000;
$(window).data('notifyAfter', +new Date() + 2000);
window.setTimeout(function() {
/* Delete the notification block in case the system time is changed backward */
if ($(window).data('notifyAfter') === notifyAfter) {
$(window).removeData('notifyAfter');
}
}, 2000);
/* this will be the starting state if no data is received from peers */
setCurrentGame(new PS.Game());
boardElem.data('last_state', currentGame.moves);
notifyLocalMove(null, newId);
boardElem.data('lightName', 'Light');
boardElem.data('darkName', 'Dark');
@ -733,17 +704,10 @@ $(function (){
const notifyAudio = new Audio(Waterdrop);
function playNotifySound(){
const now = +new Date();
const then = $(window).data('notifyAfter');
if (!then || now >= then) {
try { notifyAudio.play(); } catch (err) {}
}
}
function notify(body) {
const now = +new Date();
const then = $(window).data('notifyAfter');
if (!then || now >= then) {
try {
Notification.requestPermission(function(permission){
if (permission === 'granted') {
@ -761,22 +725,19 @@ $(function (){
disableNotify();
}
}
}
function closeNotifications(){
try {
navigator.serviceWorker.ready.then(function(registration){
async function closeNotifications() {
try {
const registration = await navigator.serviceWorker.ready;
if ('getNotifications' in registration) {
registration.getNotifications({tag: 'notice'}).then(function(notifications){
const notifications = await registration.getNotifications({tag: 'notice'});
for (const notification of notifications) {
notification.close();
}
});
}
} catch (err) {}
});
} catch (err) {}
}
function arrangeBoard(reversed) {
@ -998,7 +959,7 @@ $(function (){
$('#cb_undo').on('click', function(){
if (currentGame.canUndo) {
currentGame.undo();
$('#cb_board').data('last_state', currentGame.moves);
notifyLocalMove(currentGame, $('#cb_board').data('gameId'));
setCurrentGame(currentGame);
putState();
}
@ -1007,7 +968,7 @@ $(function (){
$('#cb_redo').on('click', function(){
if (currentGame.canRedo) {
currentGame.redo();
$('#cb_board').data('last_state', currentGame.moves);
notifyLocalMove(currentGame, $('#cb_board').data('gameId'));
setCurrentGame(currentGame, true);
putState();
}
@ -1021,7 +982,7 @@ $(function (){
debug('unable to resign', err);
}
$('#cb_board').data('last_state', currentGame.moves);
notifyLocalMove(currentGame, $('#cb_board').data('gameId'));
setCurrentGame(currentGame);
putState();
});
@ -1259,6 +1220,70 @@ $(function (){
IO.onMetaUpdate(updateSelectGameMeta);
const lastNotifyState = {};
function notifyForGame(meta, gameId) {
const notifyList = $('#cb_notify').data('gameList') || [];
if (!notifyList.includes('*') && !notifyList.includes(gameId)) {
return;
}
lastNotifyState[gameId] = lastNotifyState[gameId] || {};
const lastState = lastNotifyState[gameId];
const lastMetaState = lastState.meta || {};
const changed =
meta.status !== lastMetaState.status ||
meta.moves !== lastMetaState.moves ||
meta.timestamp !== lastMetaState.timestamp;
if (lastState.meta && changed) {
IO.getGameState(gameId).then((data) => {
let game = undefined;
try {
game = new PS.Game(JSON.stringify(data.board));
} catch (err) {
debug('failed to parse game for notification', err);
return;
}
const moves = game.moves;
if (!deepEqual(moves, lastState.moves)) {
if (!game.board.phantom && moves.length > (lastState.moves || []).length) {
const lightName = shortenName(String(data.lightName || 'Light'));
const darkName = shortenName(String(data.darkName || 'Dark'));
const message = gameMessage(game);
const gameString = `${lightName} vs. ${darkName}\n${message}`;
closeNotifications().then(() => {
notify(gameString);
});
if ($('#cb_sound').prop('checked')) {
playNotifySound();
}
}
lastState.moves = moves;
}
}).catch((err) => {
debug('failed to retrieve game data for notification', err);
});
}
lastState.meta = meta;
}
function notifyLocalMove(game, gameId) {
if (!game) {
delete lastNotifyState[gameId];
} else {
lastNotifyState[gameId] = lastNotifyState[gameId] || {};
lastNotifyState[gameId].moves = game.moves;
}
}
IO.onMetaUpdate(notifyForGame);
window.onpopstate = function(event){
const foundId = location.hash.match(/^#\/([0-9a-f]{16}\b)/);
if (foundId) {