From 3e01a7e6774fe92658d2afbb2c957afa431018b3 Mon Sep 17 00:00:00 2001 From: Sorin Davidoi Date: Fri, 28 Jul 2017 05:06:01 +0200 Subject: [PATCH] fix(web_push_notification): Do not hard reload tab (#4380) * fix(web_push_notification): Do not hard reload tab * fix(web_push_notification_worker): Guard against null subscription * refactor: Incorporate pull request feedback --- app/javascript/mastodon/features/ui/index.js | 16 +++++++++ .../service_worker/web_push_notifications.js | 35 +++++++++++++------ 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js index e667b390..b6307dd4 100644 --- a/app/javascript/mastodon/features/ui/index.js +++ b/app/javascript/mastodon/features/ui/index.js @@ -49,6 +49,10 @@ const mapStateToProps = state => ({ @connect(mapStateToProps) export default class UI extends React.PureComponent { + static contextTypes = { + router: PropTypes.object.isRequired, + } + static propTypes = { dispatch: PropTypes.func.isRequired, children: PropTypes.node, @@ -123,6 +127,14 @@ export default class UI extends React.PureComponent { this.setState({ draggingOver: false }); } + handleServiceWorkerPostMessage = ({ data }) => { + if (data.type === 'navigate') { + this.context.router.history.push(data.path); + } else { + console.warn('Unknown message type:', data.type); // eslint-disable-line no-console + } + } + componentWillMount () { window.addEventListener('resize', this.handleResize, { passive: true }); document.addEventListener('dragenter', this.handleDragEnter, false); @@ -131,6 +143,10 @@ export default class UI extends React.PureComponent { document.addEventListener('dragleave', this.handleDragLeave, false); document.addEventListener('dragend', this.handleDragEnd, false); + if ('serviceWorker' in navigator) { + navigator.serviceWorker.addEventListener('message', this.handleServiceWorkerPostMessage); + } + this.props.dispatch(refreshHomeTimeline()); this.props.dispatch(refreshNotifications()); } diff --git a/app/javascript/mastodon/service_worker/web_push_notifications.js b/app/javascript/mastodon/service_worker/web_push_notifications.js index 4a8a5776..8996d3e8 100644 --- a/app/javascript/mastodon/service_worker/web_push_notifications.js +++ b/app/javascript/mastodon/service_worker/web_push_notifications.js @@ -50,22 +50,37 @@ const makeRequest = (notification, action) => credentials: 'include', }); +const findBestClient = clients => { + const focusedClient = clients.find(client => client.focused); + const visibleClient = clients.find(client => client.visibilityState === 'visible'); + + return focusedClient || visibleClient || clients[0]; +}; + const openUrl = url => self.clients.matchAll({ type: 'window' }).then(clientList => { - if (clientList.length !== 0 && 'navigate' in clientList[0]) { // Chrome 42-48 does not support navigate - const webClients = clientList - .filter(client => /\/web\//.test(client.url)) - .sort(client => client !== 'visible'); + if (clientList.length !== 0) { + const webClients = clientList.filter(client => /\/web\//.test(client.url)); - const visibleClient = clientList.find(client => client.visibilityState === 'visible'); - const focusedClient = clientList.find(client => client.focused); + if (webClients.length !== 0) { + const client = findBestClient(webClients); - const client = webClients[0] || visibleClient || focusedClient || clientList[0]; + const { pathname } = new URL(url); - return client.navigate(url).then(client => client.focus()); - } else { - return self.clients.openWindow(url); + if (pathname.startsWith('/web/')) { + return client.focus().then(client => client.postMessage({ + type: 'navigate', + path: pathname.slice('/web/'.length - 1), + })); + } + } else if ('navigate' in clientList[0]) { // Chrome 42-48 does not support navigate + const client = findBestClient(clientList); + + return client.navigate(url).then(client => client.focus()); + } } + + return self.clients.openWindow(url); }); const removeActionFromNotification = (notification, action) => {