diff src/browser/sat_browser/notification.py @ 467:97c72fe4a5f2

browser_side: import fixes: - moved browser modules in a sat_browser packages, to avoid import conflicts with std lib (e.g. logging), and let pyjsbuild work normaly - refactored bad import practices: classes are most of time not imported directly, module is imported instead.
author Goffi <goffi@goffi.org>
date Mon, 09 Jun 2014 22:15:26 +0200
parents src/browser/notification.py@981ed669d3b3
children e11e34ac0f67
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/browser/sat_browser/notification.py	Mon Jun 09 22:15:26 2014 +0200
@@ -0,0 +1,122 @@
+from __pyjamas__ import JS, wnd
+from sat.core.log import getLogger
+log = getLogger(__name__)
+from sat.core.i18n import _
+
+from pyjamas import Window
+from pyjamas.Timer import Timer
+
+import dialog
+
+TIMER_DELAY = 5000
+
+
+class Notification(object):
+    """
+    If the browser supports it, the user allowed it to and the tab is in the
+    background, send desktop notifications on messages.
+
+    Requires both Web Notifications and Page Visibility API.
+    """
+
+    def __init__(self):
+        self.enabled = False
+        user_agent = None
+        notif_permission = None
+        JS("""
+        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;
+
+        else if (Notification.permission === 'default') {
+            Notification.requestPermission(function(permission){
+                if (permission !== 'granted')
+                    return;
+
+                self.enabled = true; //need to use self instead of this
+            });
+        }
+        """)
+
+        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):
+            log.warning("Can't find Chromium version")
+            version = 0
+        log.info("Chromium version: %d" % (version,))
+        if version < 22:
+            log.info("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.<br/>To activate notifications, click on the favicon on the left of the address bar')).show()
+            return
+
+        log.info("==> Installing Chromium notifications request workaround <==")
+        self._old_click = wnd().onclick
+        wnd().onclick = self._chromiumWorkaround
+
+    def _chromiumWorkaround(self):
+        log.info("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()