# HG changeset patch # User Goffi # Date 1395852134 -3600 # Node ID f9130176bc8da6c949f684326517ea6502885306 # Parent 20c508f9b32ad6d6e69d81765b98534d2a67e2bd 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 diff -r 20c508f9b32a -r f9130176bc8d browser_side/notification.py --- 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()