changeset 714:03e9fe91081c

browser_side: use favico.js to display alerts counter
author souliane <souliane@mailoo.org>
date Mon, 20 Jul 2015 10:18:02 +0200
parents d75935e2b279
children b2465423c76e
files README setup.py src/browser/libervia_main.py src/browser/public/favico.min.js src/browser/public/libervia.html src/browser/sat_browser/notification.py
diffstat 6 files changed, 44 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/README	Wed Jul 15 13:34:17 2015 +0200
+++ b/README	Mon Jul 20 10:18:02 2015 +0200
@@ -39,7 +39,7 @@
 
 proxy65:
 SàT (plugin_xep_0065) use nearly all the code from proxy65 (http://code.google.com/p/proxy65/) which was coded by Dave Smith (2002-2004) and maintained by Fabio Forno (2007-2008).
-As the original MIT licence allows, the code is reused and sub-licenced until GPL v3 to follow the rest of the code.
+As the original MIT licence allows, the code is reused and sublicenced under GPL v3 to follow the rest of the code.
 
 progressbar:
 SàT (jp) use ProgressBar (http://pypi.python.org/pypi/progressbar/2.2), a class coded by Nilton Volpato which allow the textual representation of progression.
@@ -51,7 +51,7 @@
 SàT use a library with high level enhancements on top of twisted, which is called wokkel (http://wokkel.ik.nu). Lot of thanks to Ralph Meijer and all other contributors.
 
 wxWidgets & wxPython:
-The Wix frontend is made with wxWidgets (www.wxwidgets.org) and its python version wxPython (wxPython), which is a really handy UI toolkit who works on most popular platforms. It can be found on probably all major Gnu/Linux distributions.
+The Wix frontend is made with wxWidgets (www.wxwidgets.org) and its python version wxPython (wxPython), which is a really handy UI toolkit who works on most popular platforms. It can be found on probably all major GNU/Linux distributions.
 
 Urwid:
 Primitivus is based on Urwid (http://excess.org/urwid/) which saved me a lot of time. It's really a great library to easily make a sophisticated interface.
@@ -60,10 +60,10 @@
 Libervia is built with a Pyjamas (http://pyjs.org), a Google Web Toolkit port for python, including Python to Javascript compiler, and Pyjamas Desktop which allow to execute the same application on the desktop or through a browser. It's really an amazing tool.
 
 Pyfeed and Xe:
-SàT core and Libervia use pyfeed and xe (http://www.blarg.net/%7Esteveha/), 2 libraries made Steve R. Hastings really useful to parse/generate xml stuff as atom feeds.
+SàT core and Libervia use pyfeed and xe (http://www.blarg.net/%7Esteveha/), 2 libraries made Steve R. Hastings really useful to parse/generate XML stuff as atom feeds.
 
 txJSON-RPC:
-Libervia use txJSON-RPC (https://launchpad.net/txjsonrpc), a twisted library to communicate with the browser's javascript throught JSON-RPC
+Libervia use txJSON-RPC (https://launchpad.net/txjsonrpc), a twisted library to communicate with the browser's javascript throught JSON-RPC.
 
 Mutagen:
 Mutagen (https://code.google.com/p/mutagen/) is an audio metadata handling library, it's use by the radiocol plugin.
@@ -74,7 +74,10 @@
     - Big Integer Library was coded by Leemon Baird (2000-2013) and is in the public domain
     - CryptoJS was coded by Jeff Mott (2009-2013) and is released under the MIT licence
     - EventEmitter was coded by Oliver Caldwell (2011-2013) and is released under the MIT licence
-As the original licences allow, the code is reused and sub-licenced until GPL v3 to follow the rest of the code.
+As the original licences allow, the code is reused and sublicenced under GPL v3 to follow the rest of the code.
+
+favico.js:
+Libervia's favicon counter is displayed with favico.js (http://lab.ejci.net/favico.js/), a library by Miroslav Magda which is dual licensed under GPL and MIT.
 
 pictures found in the sat_media repository and used by SàT and Libervia:
 Please read the credits and licence information that are given in the README and COPYING files for each work: http://repos.goffi.org/sat_media/file
--- a/setup.py	Wed Jul 15 13:34:17 2015 +0200
+++ b/setup.py	Mon Jul 20 10:18:02 2015 +0200
@@ -120,7 +120,7 @@
         os.symlink(os.path.dirname(sat_frontends.__file__), os.path.join(tmp_dir,"sat_frontends")) # FIXME: only work on unixes
         os.symlink(os.path.dirname(libervia.__file__), os.path.join(tmp_dir,"libervia")) # FIXME: only work on unixes
         for module in ('libervia_main', 'libervia_test'):
-            result = subprocess.call(['pyjsbuild', module, '-d', '--no-compile-inplace', '-I', tmp_dir, '-o', self.pyjamas_output_dir])
+            result = subprocess.call(['pyjsbuild', module, '--platforms=mozilla', '-d', '--no-compile-inplace', '-I', tmp_dir, '-o', self.pyjamas_output_dir])
             if result != 0:
                 continue
         shutil.rmtree(tmp_dir)
--- a/src/browser/libervia_main.py	Wed Jul 15 13:34:17 2015 +0200
+++ b/src/browser/libervia_main.py	Mon Jul 20 10:18:02 2015 +0200
@@ -86,6 +86,7 @@
         RootPanel().add(self.panel)
 
         self.notification = notification.Notification()
+        self.alerts_counter = notification.FaviconCounter()
         DOM.addEventPreview(self)
         self.importPlugins()
         self._register = json.RegisterCall()
@@ -642,6 +643,12 @@
     def _newAlert(self, message, title, alert_type):
         dialog.InfoDialog(title, message).show()
 
+    def updateAlertsCounter(self):
+        """Update the over whole alerts counter
+
+        """
+        self.alerts_counter.update(self.alerts_count)
+
     def _paramUpdate(self, name, value, category, refresh=True):
         """This is called when the paramUpdate signal is received, but also
         during initialization when the UI parameters values are retrieved.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/browser/public/favico.min.js	Mon Jul 20 10:18:02 2015 +0200
@@ -0,0 +1,9 @@
+/**
+ * This file is distributed with Libervia and is sublicensed under AGPL v3 (or any later version) as allowed by its original license.
+ *
+ * @license MIT
+ * @fileOverview Favico animations
+ * @author Miroslav Magda, http://blog.ejci.net
+ * @version 0.3.9
+ */
+!function(){var e=function(e){"use strict";function t(e){if(e.paused||e.ended||g)return!1;try{f.clearRect(0,0,s,l),f.drawImage(e,0,0,s,l)}catch(o){}p=setTimeout(t,S.duration,e),O.setIcon(h)}function o(e){var t=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;e=e.replace(t,function(e,t,o,n){return t+t+o+o+n+n});var o=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return o?{r:parseInt(o[1],16),g:parseInt(o[2],16),b:parseInt(o[3],16)}:!1}function n(e,t){var o,n={};for(o in e)n[o]=e[o];for(o in t)n[o]=t[o];return n}function r(){return b.hidden||b.msHidden||b.webkitHidden||b.mozHidden}e=e?e:{};var i,a,l,s,h,f,c,d,u,y,w,g,x,m,p,b,v={bgColor:"#d00",textColor:"#fff",fontFamily:"sans-serif",fontStyle:"bold",type:"circle",position:"down",animation:"slide",elementId:!1,dataUrl:!1,win:window};x={},x.ff="undefined"!=typeof InstallTrigger,x.chrome=!!window.chrome,x.opera=!!window.opera||navigator.userAgent.indexOf("Opera")>=0,x.ie=/*@cc_on!@*/!1,x.safari=Object.prototype.toString.call(window.HTMLElement).indexOf("Constructor")>0,x.supported=x.chrome||x.ff||x.opera;var C=[];w=function(){},d=g=!1;var E=function(){i=n(v,e),i.bgColor=o(i.bgColor),i.textColor=o(i.textColor),i.position=i.position.toLowerCase(),i.animation=S.types[""+i.animation]?i.animation:v.animation,b=i.win.document;var t=i.position.indexOf("up")>-1,r=i.position.indexOf("left")>-1;if(t||r)for(var d=0;d<S.types[""+i.animation].length;d++){var u=S.types[""+i.animation][d];t&&(u.y=u.y<.6?u.y-.4:u.y-2*u.y+(1-u.w)),r&&(u.x=u.x<.6?u.x-.4:u.x-2*u.x+(1-u.h)),S.types[""+i.animation][d]=u}i.type=A[""+i.type]?i.type:v.type,a=O.getIcon(),h=document.createElement("canvas"),c=document.createElement("img"),a.hasAttribute("href")?(c.setAttribute("crossOrigin","anonymous"),c.setAttribute("src",a.getAttribute("href")),c.onload=function(){l=c.height>0?c.height:32,s=c.width>0?c.width:32,h.height=l,h.width=s,f=h.getContext("2d"),M.ready()}):(c.setAttribute("src",""),l=32,s=32,c.height=l,c.width=s,h.height=l,h.width=s,f=h.getContext("2d"),M.ready())},M={};M.ready=function(){d=!0,M.reset(),w()},M.reset=function(){d&&(C=[],u=!1,y=!1,f.clearRect(0,0,s,l),f.drawImage(c,0,0,s,l),O.setIcon(h),window.clearTimeout(m),window.clearTimeout(p))},M.start=function(){if(d&&!y){var e=function(){u=C[0],y=!1,C.length>0&&(C.shift(),M.start())};if(C.length>0){y=!0;var t=function(){["type","animation","bgColor","textColor","fontFamily","fontStyle"].forEach(function(e){e in C[0].options&&(i[e]=C[0].options[e])}),S.run(C[0].options,function(){e()},!1)};u?S.run(u.options,function(){t()},!0):t()}}};var A={},I=function(e){return e.n="number"==typeof e.n?Math.abs(0|e.n):e.n,e.x=s*e.x,e.y=l*e.y,e.w=s*e.w,e.h=l*e.h,e.len=(""+e.n).length,e};A.circle=function(e){e=I(e);var t=!1;2===e.len?(e.x=e.x-.4*e.w,e.w=1.4*e.w,t=!0):e.len>=3&&(e.x=e.x-.65*e.w,e.w=1.65*e.w,t=!0),f.clearRect(0,0,s,l),f.drawImage(c,0,0,s,l),f.beginPath(),f.font=i.fontStyle+" "+Math.floor(e.h*(e.n>99?.85:1))+"px "+i.fontFamily,f.textAlign="center",t?(f.moveTo(e.x+e.w/2,e.y),f.lineTo(e.x+e.w-e.h/2,e.y),f.quadraticCurveTo(e.x+e.w,e.y,e.x+e.w,e.y+e.h/2),f.lineTo(e.x+e.w,e.y+e.h-e.h/2),f.quadraticCurveTo(e.x+e.w,e.y+e.h,e.x+e.w-e.h/2,e.y+e.h),f.lineTo(e.x+e.h/2,e.y+e.h),f.quadraticCurveTo(e.x,e.y+e.h,e.x,e.y+e.h-e.h/2),f.lineTo(e.x,e.y+e.h/2),f.quadraticCurveTo(e.x,e.y,e.x+e.h/2,e.y)):f.arc(e.x+e.w/2,e.y+e.h/2,e.h/2,0,2*Math.PI),f.fillStyle="rgba("+i.bgColor.r+","+i.bgColor.g+","+i.bgColor.b+","+e.o+")",f.fill(),f.closePath(),f.beginPath(),f.stroke(),f.fillStyle="rgba("+i.textColor.r+","+i.textColor.g+","+i.textColor.b+","+e.o+")","number"==typeof e.n&&e.n>999?f.fillText((e.n>9999?9:Math.floor(e.n/1e3))+"k+",Math.floor(e.x+e.w/2),Math.floor(e.y+e.h-.2*e.h)):f.fillText(e.n,Math.floor(e.x+e.w/2),Math.floor(e.y+e.h-.15*e.h)),f.closePath()},A.rectangle=function(e){e=I(e);var t=!1;2===e.len?(e.x=e.x-.4*e.w,e.w=1.4*e.w,t=!0):e.len>=3&&(e.x=e.x-.65*e.w,e.w=1.65*e.w,t=!0),f.clearRect(0,0,s,l),f.drawImage(c,0,0,s,l),f.beginPath(),f.font=i.fontStyle+" "+Math.floor(e.h*(e.n>99?.9:1))+"px "+i.fontFamily,f.textAlign="center",f.fillStyle="rgba("+i.bgColor.r+","+i.bgColor.g+","+i.bgColor.b+","+e.o+")",f.fillRect(e.x,e.y,e.w,e.h),f.fillStyle="rgba("+i.textColor.r+","+i.textColor.g+","+i.textColor.b+","+e.o+")","number"==typeof e.n&&e.n>999?f.fillText((e.n>9999?9:Math.floor(e.n/1e3))+"k+",Math.floor(e.x+e.w/2),Math.floor(e.y+e.h-.2*e.h)):f.fillText(e.n,Math.floor(e.x+e.w/2),Math.floor(e.y+e.h-.15*e.h)),f.closePath()};var T=function(e,t){t=("string"==typeof t?{animation:t}:t)||{},w=function(){try{if("number"==typeof e?e>0:""!==e){var n={type:"badge",options:{n:e}};if("animation"in t&&S.types[""+t.animation]&&(n.options.animation=""+t.animation),"type"in t&&A[""+t.type]&&(n.options.type=""+t.type),["bgColor","textColor"].forEach(function(e){e in t&&(n.options[e]=o(t[e]))}),["fontStyle","fontFamily"].forEach(function(e){e in t&&(n.options[e]=t[e])}),C.push(n),C.length>100)throw new Error("Too many badges requests in queue.");M.start()}else M.reset()}catch(r){throw new Error("Error setting badge. Message: "+r.message)}},d&&w()},U=function(e){w=function(){try{var t=e.width,o=e.height,n=document.createElement("img"),r=o/l>t/s?t/s:o/l;n.setAttribute("crossOrigin","anonymous"),n.setAttribute("src",e.getAttribute("src")),n.height=o/r,n.width=t/r,f.clearRect(0,0,s,l),f.drawImage(n,0,0,s,l),O.setIcon(h)}catch(i){throw new Error("Error setting image. Message: "+i.message)}},d&&w()},R=function(e){w=function(){try{if("stop"===e)return g=!0,M.reset(),void(g=!1);e.addEventListener("play",function(){t(this)},!1)}catch(o){throw new Error("Error setting video. Message: "+o.message)}},d&&w()},L=function(e){if(window.URL&&window.URL.createObjectURL||(window.URL=window.URL||{},window.URL.createObjectURL=function(e){return e}),x.supported){var o=!1;navigator.getUserMedia=navigator.getUserMedia||navigator.oGetUserMedia||navigator.msGetUserMedia||navigator.mozGetUserMedia||navigator.webkitGetUserMedia,w=function(){try{if("stop"===e)return g=!0,M.reset(),void(g=!1);o=document.createElement("video"),o.width=s,o.height=l,navigator.getUserMedia({video:!0,audio:!1},function(e){o.src=URL.createObjectURL(e),o.play(),t(o)},function(){})}catch(n){throw new Error("Error setting webcam. Message: "+n.message)}},d&&w()}},O={};O.getIcon=function(){var e=!1,t=function(){for(var e=b.getElementsByTagName("head")[0].getElementsByTagName("link"),t=e.length,o=t-1;o>=0;o--)if(/(^|\s)icon(\s|$)/i.test(e[o].getAttribute("rel")))return e[o];return!1};return i.element?e=i.element:i.elementId?(e=b.getElementById(i.elementId),e.setAttribute("href",e.getAttribute("src"))):(e=t(),e===!1&&(e=b.createElement("link"),e.setAttribute("rel","icon"),b.getElementsByTagName("head")[0].appendChild(e))),e.setAttribute("type","image/png"),e},O.setIcon=function(e){var t=e.toDataURL("image/png");if(i.dataUrl&&i.dataUrl(t),i.element)i.element.setAttribute("href",t),i.element.setAttribute("src",t);else if(i.elementId){var o=b.getElementById(i.elementId);o.setAttribute("href",t),o.setAttribute("src",t)}else if(x.ff||x.opera){var n=a;a=b.createElement("link"),x.opera&&a.setAttribute("rel","icon"),a.setAttribute("rel","icon"),a.setAttribute("type","image/png"),b.getElementsByTagName("head")[0].appendChild(a),a.setAttribute("href",t),n.parentNode&&n.parentNode.removeChild(n)}else a.setAttribute("href",t)};var S={};return S.duration=40,S.types={},S.types.fade=[{x:.4,y:.4,w:.6,h:.6,o:0},{x:.4,y:.4,w:.6,h:.6,o:.1},{x:.4,y:.4,w:.6,h:.6,o:.2},{x:.4,y:.4,w:.6,h:.6,o:.3},{x:.4,y:.4,w:.6,h:.6,o:.4},{x:.4,y:.4,w:.6,h:.6,o:.5},{x:.4,y:.4,w:.6,h:.6,o:.6},{x:.4,y:.4,w:.6,h:.6,o:.7},{x:.4,y:.4,w:.6,h:.6,o:.8},{x:.4,y:.4,w:.6,h:.6,o:.9},{x:.4,y:.4,w:.6,h:.6,o:1}],S.types.none=[{x:.4,y:.4,w:.6,h:.6,o:1}],S.types.pop=[{x:1,y:1,w:0,h:0,o:1},{x:.9,y:.9,w:.1,h:.1,o:1},{x:.8,y:.8,w:.2,h:.2,o:1},{x:.7,y:.7,w:.3,h:.3,o:1},{x:.6,y:.6,w:.4,h:.4,o:1},{x:.5,y:.5,w:.5,h:.5,o:1},{x:.4,y:.4,w:.6,h:.6,o:1}],S.types.popFade=[{x:.75,y:.75,w:0,h:0,o:0},{x:.65,y:.65,w:.1,h:.1,o:.2},{x:.6,y:.6,w:.2,h:.2,o:.4},{x:.55,y:.55,w:.3,h:.3,o:.6},{x:.5,y:.5,w:.4,h:.4,o:.8},{x:.45,y:.45,w:.5,h:.5,o:.9},{x:.4,y:.4,w:.6,h:.6,o:1}],S.types.slide=[{x:.4,y:1,w:.6,h:.6,o:1},{x:.4,y:.9,w:.6,h:.6,o:1},{x:.4,y:.9,w:.6,h:.6,o:1},{x:.4,y:.8,w:.6,h:.6,o:1},{x:.4,y:.7,w:.6,h:.6,o:1},{x:.4,y:.6,w:.6,h:.6,o:1},{x:.4,y:.5,w:.6,h:.6,o:1},{x:.4,y:.4,w:.6,h:.6,o:1}],S.run=function(e,t,o,a){var l=S.types[r()?"none":i.animation];return a=o===!0?"undefined"!=typeof a?a:l.length-1:"undefined"!=typeof a?a:0,t=t?t:function(){},a<l.length&&a>=0?(A[i.type](n(e,l[a])),m=setTimeout(function(){o?a-=1:a+=1,S.run(e,t,o,a)},S.duration),O.setIcon(h),void 0):void t()},E(),{badge:T,video:R,image:U,webcam:L,reset:M.reset,browser:{supported:x.supported}}};"undefined"!=typeof define&&define.amd?define([],function(){return e}):"undefined"!=typeof module&&module.exports?module.exports=e:this.Favico=e}();
--- a/src/browser/public/libervia.html	Wed Jul 15 13:34:17 2015 +0200
+++ b/src/browser/public/libervia.html	Mon Jul 20 10:18:02 2015 +0200
@@ -27,6 +27,7 @@
 </head>
 <body bgcolor="white">
 <script language="javascript" src="bootstrap.js"></script>
+<script language="javascript" src="favico.min.js"></script>
 <iframe id='__pygwt_historyFrame' style='display:none;width:0;height:0;border:0'></iframe>
 </body>
 </html>
--- a/src/browser/sat_browser/notification.py	Wed Jul 15 13:34:17 2015 +0200
+++ b/src/browser/sat_browser/notification.py	Mon Jul 20 10:18:02 2015 +0200
@@ -5,6 +5,7 @@
 
 from pyjamas import Window
 from pyjamas.Timer import Timer
+import favico.min.js
 
 import dialog
 
@@ -120,3 +121,20 @@
         if self.isHidden():
             self._notify(title, body, icon)
             self.highlightTab()
+
+
+class FaviconCounter(object):
+    """Display numbers over the favicon to signal e.g. waiting messages"""
+
+    def __init__(self):
+        # XXX: the file favico.min.js is loaded from public/libervia.html because I get NS_ERROR_FAILURE when it's loaded with Pyjamas. It sounds like a context issue, with the favicon not being found.
+
+        JS("""
+        self.counter = new top.Favico({
+            animation : 'slide',
+            bgColor: '#5CB85C',
+        });
+        """)
+
+    def update(self, count):
+        self.counter.badge(count)