about summary refs log tree commit diff
path: root/app
diff options
context:
space:
mode:
authorSorin Davidoi <sorin.davidoi@gmail.com>2017-07-28 05:06:01 +0200
committerEugen Rochko <eugen@zeonfederated.com>2017-07-28 05:06:01 +0200
commit3e01a7e6774fe92658d2afbb2c957afa431018b3 (patch)
treefaf328cff47b6660400a7865d7b6f5c86b1bf96e /app
parent0f92119cebbebc463960c5532a049277ec1706be (diff)
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 (limited to 'app')
-rw-r--r--app/javascript/mastodon/features/ui/index.js16
-rw-r--r--app/javascript/mastodon/service_worker/web_push_notifications.js35
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 e667b390b..b6307dd4c 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 4a8a57767..8996d3e83 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) => {