commit: 3e01a7e6774fe92658d2afbb2c957afa431018b3
parent: 0f92119cebbebc463960c5532a049277ec1706be
Author: Sorin Davidoi <sorin.davidoi@gmail.com>
Date: Fri, 28 Jul 2017 05:06:01 +0200
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
Diffstat:
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
@@ -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
@@ -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) => {