changeset 423:f9130176bc8d

browser side: notifications enhancements: - moved sevaral part from Javascript to Python (is hidden, self.enabled) - fixed Notification call (a new was missing) - fixed notification closing: after 5 s, notification is closed (former behaviour was to let the notification visible until manual close) - workaround for Chromium behaviour: notification permission request is not possible on page loading, it need a user interaction. So, if Chromium is detected, Window.onClick is used to request the permission on first click. - for Chromium < 32 (and >= 22) a dialog is shown on loading to indicate how to activate manually notifications - add browser tab highlighting (for pinned tabs), number of unseen notifications is shown in page title
author Goffi <goffi@goffi.org>
date Wed, 26 Mar 2014 17:42:14 +0100 (2014-03-26)
parents 20c508f9b32a
children 4ba4b099d266
files browser_side/notification.py
diffstat 1 files changed, 85 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/browser_side/notification.py	Wed Mar 26 17:34:01 2014 +0100
+++ b/browser_side/notification.py	Wed Mar 26 17:42:14 2014 +0100
@@ -1,4 +1,10 @@
-from __pyjamas__ import JS
+from __pyjamas__ import JS, wnd
+from pyjamas import Window
+from pyjamas.Timer import Timer
+from browser_side import dialog
+from sat.core.i18n import _
+
+TIMER_DELAY = 5000
 
 
 class Notification(object):
@@ -10,15 +16,20 @@
     """
 
     def __init__(self):
+        self.enabled = False
+        user_agent = None
+        notif_permission = None
         JS("""
-        this.enabled = false;
-
         if (!('hidden' in document))
             document.hidden = false;
 
+        user_agent = navigator.userAgent
+
         if (!('Notification' in window))
             return;
 
+        notif_permission = Notification.permission
+
         if (Notification.permission === 'granted')
             this.enabled = true;
 
@@ -27,19 +38,81 @@
                 if (permission !== 'granted')
                     return;
 
-                this.enabled = true;
+                self.enabled = true; //need to use self instead of this
             });
         }
         """)
 
-    def notify(self, title, body, icon='/media/icons/apps/48/sat.png'):
-        JS("""
-        if (this.enabled && document.hidden) {
-            notification = Notification(title, {body: body, icon: icon});
+        if "Chrome" in user_agent and notif_permission not in ['granted', 'denied']:
+            self.user_agent = user_agent
+            self._installChromiumWorkaround()
+
+        wnd().onfocus = self.onFocus
+        # wnd().onblur = self.onBlur
+        self._notif_count = 0
+        self._orig_title = Window.getTitle()
+
+    def _installChromiumWorkaround(self):
+        # XXX: Workaround for Chromium behaviour, it's doens't manage requestPermission on onLoad event
+        # see https://code.google.com/p/chromium/issues/detail?id=274284
+        # FIXME: need to be removed if Chromium behaviour changes
+        try:
+            version_full = [s for s in self.user_agent.split() if "Chrome" in s][0].split('/')[1]
+            version = int(version_full.split('.')[0])
+        except (IndexError, ValueError):
+            print "Can't find Chromium version"
+            version = 0
+        print "Chromium version: %d" % (version,)
+        if version < 22:
+            print "Notification use the old prefixed version or are unmanaged"
+            return
+        if version < 32:
+            dialog.InfoDialog(_("Notifications activation for Chromium"), _('You need to activate notifications manually for your Chromium version.\nTo activate notifications, click on the favicon on the left of the address bar')).show()
+            return
+
+        print "==> Installing Chromium notifications request workaround <=="
+        self._old_click = wnd().onclick
+        wnd().onclick = self._chromiumWorkaround
 
-            // Probably won’t work, but it doesn’t hurt to try.
-            notification.addEventListener('click', function() {
-                window.focus();
+    def _chromiumWorkaround(self):
+        print "Activating workaround"
+        JS("""
+            Notification.requestPermission(function(permission){
+                if (permission !== 'granted')
+                    return;
+                self.enabled = true; //need to use self instead of this
             });
-        }
         """)
+        wnd().onclick = self._old_click
+
+    def onFocus(self):
+        Window.setTitle(self._orig_title)
+        self._notif_count = 0
+
+    # def onBlur(self):
+    #     pass
+
+    def isHidden(self):
+        JS("""return document.hidden;""")
+
+    def _notify(self, title, body, icon):
+        if not self.enabled:
+            return
+        notification = None
+        JS("""
+           notification = new Notification(title, {body: body, icon: icon});
+           // Probably won’t work, but it doesn’t hurt to try.
+           notification.addEventListener('click', function() {
+               window.focus();
+           });
+           """)
+        notification.onshow = lambda: Timer(TIMER_DELAY, lambda timer: notification.close())
+
+    def highlightTab(self):
+        self._notif_count += 1
+        Window.setTitle("%s (%d)" % (self._orig_title, self._notif_count))
+
+    def notify(self, title, body, icon='/media/icons/apps/48/sat.png'):
+        if self.isHidden():
+            self._notify(title, body, icon)
+            self.highlightTab()