diff --git a/js/chess.js b/js/chess.js index 601d837..42ca822 100644 --- a/js/chess.js +++ b/js/chess.js @@ -503,7 +503,7 @@ function renderBoard(board){ if (board.move && board.move.took === 'k') { msg = (isDark(board.move.side) ? 'Dark' : 'Light') + ' player won!'; } else { - msg = (isDark(board.player) ? 'Dark' : 'Light') + " player's move"; + msg = (isDark(board.player) ? 'Dark' : 'Light') + " player's turn"; } $('#cb_message').text(msg); @@ -540,12 +540,25 @@ function setVisibleBoard(board, live){ } function setCurrentBoard(board){ - $('#cb_board').data('board', board); + const cb_board = $('#cb_board').first(); + cb_board.data('board', board); + + const boardState = JSON.stringify(board); /* navigation should not include the redo stack */ - const visible = cloneJSON(board); + const visible = JSON.parse(boardState); delete visible.subsequent; setVisibleBoard(visible, true); + + if ($('#cb_notify')[0].checked && boardState !== cb_board.data('last_state')) { + /* ignore partial moves and undo/redo */ + if (!board.phantom && !board.subsequent) { + const gameString = cb_board.data('lightName') + ' vs. ' + cb_board.data('darkName'); + notify(gameString + '\n' + $('#cb_message').text()); + } + } + + cb_board.data('last_state', boardState); } function randomId(){ @@ -564,7 +577,7 @@ function putState(board){ var gameId = boardElem.data('gameId'); var game = gun.get(PacoSakoUUID).get('games').get(gameId); var state = JSON.stringify(board); - $('#cb_board').data('skip_notify', state); + boardElem.data('last_state', state); game.put({ board: state }); putMeta(); } @@ -602,36 +615,37 @@ function switchGameId(newId){ boardElem.data('gameId', newId); location.hash = '#/' + newId; + const notifyAfter = new Date().getTime() + 2000; + $(window).data('notifyAfter', new Date().getTime() + 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); + closeNotifications(); + /* this will be the starting state if no data is received from peers */ var newBoard = initialBoard(); setCurrentBoard(newBoard); + boardElem.data('last_state', JSON.stringify(newBoard)); - $('#cb_notify')[0].checked = false; + boardElem.data('lightName', 'Light'); + boardElem.data('darkName', 'Dark'); $('#cb_light_name').val(''); $('#cb_dark_name').val(''); - $('#cb_board').removeData('skip_notify'); gun.get(PacoSakoUUID).get('games').get(newId).on(function(d){ if (d && d.board && $('#cb_board').data('gameId') === newId) { const board = JSON.parse(d.board); - const cb_board = $('#cb_board').first(); - if ($('#cb_notify')[0].checked && cb_board.data('skip_notify') !== d.board) { - /* ignore partial moves and undo/redo */ - if (!board.phantom && !board.subsequent) { - if (board.move && board.move.took === 'k') { - notify((isDark(board.move.side) ? 'Dark' : 'Light') + ' player won!'); - } else { - notify((isDark(board.player) ? 'Dark' : 'Light') + ' player\'s turn'); - } - $('#cb_board').data('skip_notify', d.board); - } - } setCurrentBoard(board); } }); gun.get(PacoSakoUUID).get('meta').get(newId).on(function(d){ if (d && $('#cb_board').data('gameId') === newId) { + $('#cb_board').data('lightName', d.lightName || 'Light'); + $('#cb_board').data('darkName', d.darkName || 'Dark'); $('#cb_light_name').val(d.lightName || ''); $('#cb_dark_name').val(d.darkName || ''); } @@ -663,26 +677,40 @@ function requestNotify(){ } function notify(body) { - try { - Notification.requestPermission(function(permission){ - if (permission === 'granted') { - navigator.serviceWorker.ready.then(function(registration){ - registration.showNotification('Paco Ŝako', { - badge: 'svg/Chess_klt45.svg', - icon: 'svg/Chess_klt45.svg', - body: body, - tag: 'notice', + const now = new Date().getTime(); + const then = $(window).data('notifyAfter'); + if (!then || now >= then) { + try { + Notification.requestPermission(function(permission){ + if (permission === 'granted') { + navigator.serviceWorker.ready.then(function(registration){ + registration.showNotification('Paco Ŝako', { + body: body, + tag: 'notice', + }); }); - }); - } else if (permission === 'denied') { - disableNotify(); - } - }); - } catch (err) { - disableNotify(); + } else if (permission === 'denied') { + disableNotify(); + } + }); + } catch (err) { + disableNotify(); + } } } +function closeNotifications(){ + try { + navigator.serviceWorker.ready.then(function(registration){ + registration.getNotifications({tag: 'notice'}).then(function(notifications){ + for (const notification of notifications) { + notification.close(); + } + }); + }); + } catch (err) {} +} + $(function (){ try { if (Notification.permission === 'denied') { @@ -694,6 +722,27 @@ $(function (){ disableNotify(); } + if ('localStorage' in window) { + function updateNotify(newValue){ + const doNotify = newValue === 'on'; + const cb_notify = $('#cb_notify')[0]; + if (doNotify) { + if (!cb_notify.checked) { + cb_notify.checked = true; + requestNotify(); + } + } else if (cb_notify.checked) { + cb_notify.checked = false; + } + } + $(window).on('storage', function(event){ + if (event.originalEvent.key === '/pacosako/notify') { + updateNotify(event.originalEvent.newValue); + } + }); + updateNotify(window.localStorage.getItem('/pacosako/notify')); + } + $('.cb-square').droppable({ accept: '.cb-piece', disabled: true, @@ -708,6 +757,7 @@ $(function (){ dragged.appendTo('#cb_hidden'); var newBoard = movePiece($('#cb_board').data('board'), type[1], from, to); + renderBoard(newBoard); putState(newBoard); }, }); @@ -823,6 +873,9 @@ $(function (){ }); $('#cb_notify').on('change', function(){ + if ('localStorage' in window) { + window.localStorage.setItem('/pacosako/notify', this.checked ? 'on' : 'off'); + } if (this.checked) { requestNotify(); }