comparison browser_side/notification.py @ 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
parents 835a8ae799e7
children 4ba4b099d266
comparison
equal deleted inserted replaced
422:20c508f9b32a 423:f9130176bc8d
1 from __pyjamas__ import JS 1 from __pyjamas__ import JS, wnd
2 from pyjamas import Window
3 from pyjamas.Timer import Timer
4 from browser_side import dialog
5 from sat.core.i18n import _
6
7 TIMER_DELAY = 5000
2 8
3 9
4 class Notification(object): 10 class Notification(object):
5 """ 11 """
6 If the browser supports it, the user allowed it to and the tab is in the 12 If the browser supports it, the user allowed it to and the tab is in the
8 14
9 Requires both Web Notifications and Page Visibility API. 15 Requires both Web Notifications and Page Visibility API.
10 """ 16 """
11 17
12 def __init__(self): 18 def __init__(self):
19 self.enabled = False
20 user_agent = None
21 notif_permission = None
13 JS(""" 22 JS("""
14 this.enabled = false;
15
16 if (!('hidden' in document)) 23 if (!('hidden' in document))
17 document.hidden = false; 24 document.hidden = false;
18 25
26 user_agent = navigator.userAgent
27
19 if (!('Notification' in window)) 28 if (!('Notification' in window))
20 return; 29 return;
30
31 notif_permission = Notification.permission
21 32
22 if (Notification.permission === 'granted') 33 if (Notification.permission === 'granted')
23 this.enabled = true; 34 this.enabled = true;
24 35
25 else if (Notification.permission === 'default') { 36 else if (Notification.permission === 'default') {
26 Notification.requestPermission(function(permission){ 37 Notification.requestPermission(function(permission){
27 if (permission !== 'granted') 38 if (permission !== 'granted')
28 return; 39 return;
29 40
30 this.enabled = true; 41 self.enabled = true; //need to use self instead of this
31 }); 42 });
32 } 43 }
33 """) 44 """)
34 45
46 if "Chrome" in user_agent and notif_permission not in ['granted', 'denied']:
47 self.user_agent = user_agent
48 self._installChromiumWorkaround()
49
50 wnd().onfocus = self.onFocus
51 # wnd().onblur = self.onBlur
52 self._notif_count = 0
53 self._orig_title = Window.getTitle()
54
55 def _installChromiumWorkaround(self):
56 # XXX: Workaround for Chromium behaviour, it's doens't manage requestPermission on onLoad event
57 # see https://code.google.com/p/chromium/issues/detail?id=274284
58 # FIXME: need to be removed if Chromium behaviour changes
59 try:
60 version_full = [s for s in self.user_agent.split() if "Chrome" in s][0].split('/')[1]
61 version = int(version_full.split('.')[0])
62 except (IndexError, ValueError):
63 print "Can't find Chromium version"
64 version = 0
65 print "Chromium version: %d" % (version,)
66 if version < 22:
67 print "Notification use the old prefixed version or are unmanaged"
68 return
69 if version < 32:
70 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()
71 return
72
73 print "==> Installing Chromium notifications request workaround <=="
74 self._old_click = wnd().onclick
75 wnd().onclick = self._chromiumWorkaround
76
77 def _chromiumWorkaround(self):
78 print "Activating workaround"
79 JS("""
80 Notification.requestPermission(function(permission){
81 if (permission !== 'granted')
82 return;
83 self.enabled = true; //need to use self instead of this
84 });
85 """)
86 wnd().onclick = self._old_click
87
88 def onFocus(self):
89 Window.setTitle(self._orig_title)
90 self._notif_count = 0
91
92 # def onBlur(self):
93 # pass
94
95 def isHidden(self):
96 JS("""return document.hidden;""")
97
98 def _notify(self, title, body, icon):
99 if not self.enabled:
100 return
101 notification = None
102 JS("""
103 notification = new Notification(title, {body: body, icon: icon});
104 // Probably won’t work, but it doesn’t hurt to try.
105 notification.addEventListener('click', function() {
106 window.focus();
107 });
108 """)
109 notification.onshow = lambda: Timer(TIMER_DELAY, lambda timer: notification.close())
110
111 def highlightTab(self):
112 self._notif_count += 1
113 Window.setTitle("%s (%d)" % (self._orig_title, self._notif_count))
114
35 def notify(self, title, body, icon='/media/icons/apps/48/sat.png'): 115 def notify(self, title, body, icon='/media/icons/apps/48/sat.png'):
36 JS(""" 116 if self.isHidden():
37 if (this.enabled && document.hidden) { 117 self._notify(title, body, icon)
38 notification = Notification(title, {body: body, icon: icon}); 118 self.highlightTab()
39
40 // Probably won’t work, but it doesn’t hurt to try.
41 notification.addEventListener('click', function() {
42 window.focus();
43 });
44 }
45 """)