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; animate = false;
} }
$('#cb_board').data('last_state', currentGame.moves); notifyLocalMove(currentGame, $('#cb_board').data('gameId'));
setCurrentGame(currentGame, animate); setCurrentGame(currentGame, animate);
putState(); putState();
} }
@ -404,28 +404,8 @@ $(function (){
} }
function setCurrentGame(game, animate) { function setCurrentGame(game, animate) {
closeNotifications();
currentGame = game; currentGame = game;
setVisibleGame(game, animate); 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(){ function randomId(){
@ -588,7 +568,7 @@ $(function (){
function putState() { function putState() {
const boardElem = $('#cb_board'); const boardElem = $('#cb_board');
const gameId = boardElem.data('gameId'); const gameId = boardElem.data('gameId');
boardElem.data('last_state', currentGame.moves); notifyLocalMove(currentGame, boardElem.data('gameId'));
putMeta({ board: JSON.parse(currentGame.toJSON()) }); putMeta({ board: JSON.parse(currentGame.toJSON()) });
} }
@ -640,18 +620,9 @@ $(function (){
boardElem.data('modified', 0); boardElem.data('modified', 0);
history.replaceState(null, document.title, '#/' + newId); 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 */ /* this will be the starting state if no data is received from peers */
setCurrentGame(new PS.Game()); setCurrentGame(new PS.Game());
boardElem.data('last_state', currentGame.moves); notifyLocalMove(null, newId);
boardElem.data('lightName', 'Light'); boardElem.data('lightName', 'Light');
boardElem.data('darkName', 'Dark'); boardElem.data('darkName', 'Dark');
@ -733,49 +704,39 @@ $(function (){
const notifyAudio = new Audio(Waterdrop); const notifyAudio = new Audio(Waterdrop);
function playNotifySound(){ function playNotifySound(){
const now = +new Date(); try { notifyAudio.play(); } catch (err) {}
const then = $(window).data('notifyAfter');
if (!then || now >= then) {
try { notifyAudio.play(); } catch (err) {}
}
} }
function notify(body) { function notify(body) {
const now = +new Date(); try {
const then = $(window).data('notifyAfter'); Notification.requestPermission(function(permission){
if (!then || now >= then) { if (permission === 'granted') {
try { navigator.serviceWorker.ready.then(function(registration){
Notification.requestPermission(function(permission){ registration.showNotification('Paco Ŝako', {
if (permission === 'granted') { body: body,
navigator.serviceWorker.ready.then(function(registration){ tag: 'notice',
registration.showNotification('Paco Ŝako', {
body: body,
tag: 'notice',
});
}); });
} else if (permission === 'denied') { });
disableNotify(); } else if (permission === 'denied') {
} disableNotify();
}); }
} catch (err) { });
disableNotify(); } catch (err) {
} disableNotify();
} }
} }
function closeNotifications(){ async function closeNotifications() {
try { try {
navigator.serviceWorker.ready.then(function(registration){ const registration = await navigator.serviceWorker.ready;
try {
if ('getNotifications' in registration) { 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(); for (const notification of notifications) {
} notification.close();
}); }
} }
} catch (err) {}
});
} catch (err) {} } catch (err) {}
} }
@ -998,7 +959,7 @@ $(function (){
$('#cb_undo').on('click', function(){ $('#cb_undo').on('click', function(){
if (currentGame.canUndo) { if (currentGame.canUndo) {
currentGame.undo(); currentGame.undo();
$('#cb_board').data('last_state', currentGame.moves); notifyLocalMove(currentGame, $('#cb_board').data('gameId'));
setCurrentGame(currentGame); setCurrentGame(currentGame);
putState(); putState();
} }
@ -1007,7 +968,7 @@ $(function (){
$('#cb_redo').on('click', function(){ $('#cb_redo').on('click', function(){
if (currentGame.canRedo) { if (currentGame.canRedo) {
currentGame.redo(); currentGame.redo();
$('#cb_board').data('last_state', currentGame.moves); notifyLocalMove(currentGame, $('#cb_board').data('gameId'));
setCurrentGame(currentGame, true); setCurrentGame(currentGame, true);
putState(); putState();
} }
@ -1021,7 +982,7 @@ $(function (){
debug('unable to resign', err); debug('unable to resign', err);
} }
$('#cb_board').data('last_state', currentGame.moves); notifyLocalMove(currentGame, $('#cb_board').data('gameId'));
setCurrentGame(currentGame); setCurrentGame(currentGame);
putState(); putState();
}); });
@ -1259,6 +1220,70 @@ $(function (){
IO.onMetaUpdate(updateSelectGameMeta); 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){ window.onpopstate = function(event){
const foundId = location.hash.match(/^#\/([0-9a-f]{16}\b)/); const foundId = location.hash.match(/^#\/([0-9a-f]{16}\b)/);
if (foundId) { if (foundId) {