changeset 201:aa76793da353

server + browser: message warning level/sending refactoring: - widgets now manage themselves warning level - widgets now manage themselves text entered (if they are selectable, onTextEntered must be present) - Unibox now default to selected widget/status bar, except if a hook syntax is used (e.g. "@@: public microblog") - warning message is now GROUP (in blue with default theme) when sending a message to a MUC room (instead of green before) - "@.*: " syntaxes are now fully managed by browser, no more by server
author Goffi <goffi@goffi.org>
date Sun, 07 Apr 2013 22:33:55 +0200
parents 0f5c2f799913
children 2bc6cf004e61
files browser_side/base_widget.py browser_side/panels.py libervia.tac
diffstat 3 files changed, 125 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/browser_side/base_widget.py	Mon Mar 25 14:09:10 2013 +0100
+++ b/browser_side/base_widget.py	Sun Apr 07 22:33:55 2013 +0200
@@ -284,6 +284,22 @@
             self.addClickListener(self)
         self.__selectable = selectable
 
+    def getWarningData(self):
+        """ Return exposition warning level when this widget is selected and something is sent to it
+        This method should be overriden by children
+        @return: tuple (warning level type/HTML msg). Type can be one of:
+            - PUBLIC
+            - GROUP
+            - ONE2ONE
+            - MISC
+            - NONE
+        """
+        if not self.__selectable:
+            print "ERROR: getWarningLevel must not be called for an unselectable widget"
+            raise Exception
+        # TODO: cleaner warning types (more general constants)
+        return ("NONE", None)
+
     def setWidget(self, widget, scrollable=True):
         """Set the widget that will be in the body of the LiberviaWidget
         @param widget: widget to put in the body
--- a/browser_side/panels.py	Mon Mar 25 14:09:10 2013 +0100
+++ b/browser_side/panels.py	Sun Apr 07 22:33:55 2013 +0200
@@ -87,21 +87,23 @@
             
 
     def showWarning(self, target_data):
-        type, target = target_data
-        if type == "PUBLIC":
-            msg = "This message will be PUBLIC and everybody will be able to see it, even people you don't know"
+        target_hook, _type, msg = target_data
+        if _type == "NONE":
+            return
+        if not msg:
+            print "WARNING: no msg set uniBox warning"
+            return
+        if _type == "PUBLIC":
             style = "targetPublic"
-        elif type == "GROUP":
-            msg = "This message will be published for all the people of the group <span class='warningTarget'>%s</span>" % (target or '')
+        elif _type == "GROUP":
             style = "targetGroup"
-        elif type == "STATUS":
+        elif _type == "STATUS":
             msg = "This will be your new status message"
             style = "targetStatus"
-        elif type == "ONE2ONE":
-            msg = "This message will be sent to your contact <span class='warningTarget'>%s</span>" % target
+        elif _type == "ONE2ONE":
             style = "targetOne2One"
         else:
-            print "WARNING: undetermined target for this message"
+            print "ERROR: unknown message type"
             return
         contents = HTML(msg)
 
@@ -115,7 +117,6 @@
         left = 0
         top  = 0 #max(0, self.getAbsoluteTop() - contents.getOffsetHeight() - 2)   
         self._popup.setPopupPosition(left, top)
-        self._popup.setPopupPosition(left, top)
         self._popup.show()
 
     def _timeCb(self, timer):
@@ -125,30 +126,47 @@
             self._popup = None
 
     def _getTarget(self, txt):
-        """Say who will receive the messsage
-        Return a tuple (target_type, target info)"""
-        type = None
-        target = None
-        if txt.startswith('@@: '):
-            type = "PUBLIC"
+        """ Say who will receive the messsage
+        @return: a tuple (selected, target_type, target info) with:
+            - target_hook: None if we use the selected widget, (msg, data) if we have a hook (e.g. "@@: " for a public blog), where msg is the parsed message (i.e. without the "hook key: "@@: bla" become ("bla", None))
+            - target_type: one of PUBLIC, GROUP, ONE2ONE, STATUS, MISC
+            - msg: HTML message which will appear in the privacy warning banner """
+        target = self._selected_cache
+        
+        def getSelectedOrStatus():
+            if target:
+                _type, msg = target.getWarningData()
+                target_hook = None # we use the selected widget, not a hook
+            else:
+                _type, msg = "STATUS", "This will be your new status message"
+                target_hook = (txt, None)
+            return (target_hook, _type, msg)
+
+        if not txt.startswith('@'):
+            target_hook, _type, msg = getSelectedOrStatus()
+        elif txt.startswith('@@: '):
+            _type = "PUBLIC"
+            msg = MicroblogPanel.warning_msg_public
+            target_hook = (txt[4:], None) 
         elif txt.startswith('@'):
-            type = "GROUP"
             _end = txt.find(': ')
             if _end == -1:
-                type = "STATUS"
+                target_hook, _type, msg = getSelectedOrStatus()
             else:
-                target = txt[1:_end] #only one target group is managed for the moment
-                if not target in self.host.contact_panel.getGroups():
-                    target = None
-        elif self._selected_cache == None:
-            type = "STATUS"
-        elif isinstance(self._selected_cache, ChatPanel):
-            type = "ONE2ONE"
-            target = str(self._selected_cache.target)
+                group = txt[1:_end] #only one target group is managed for the moment
+                if not group or not group in self.host.contact_panel.getGroups():
+                    # the group doesn't exists, we ignore the key
+                    group = None
+                    target_hook, _type, msg = getSelectedOrStatus()
+                else:
+                    _type = "GROUP"
+                    msg = MicroblogPanel.warning_msg_group % group
+                    target_hook = (txt[_end+2:], group)
         else:
-            print "Unknown selected host:",self._selected_cache
-            type = "UNKNOWN"
-        return (type, target)
+            print "ERROR: Unknown target"
+            target_hook, _type, msg = getSelectedOrStatus()
+        
+        return (target_hook, _type, msg)
 
     def onBrowserEvent(self, event):
         #XXX: woraroung a pyjamas bug: self.currentEvent is not set
@@ -159,27 +177,31 @@
 
     def onKeyPress(self, sender, keycode, modifiers):
         _txt = self.getText()
+        target = self._getTarget(_txt)
         if not self._popup:
-            self.showWarning(self._getTarget(_txt))
-        else:
-            _target = self._getTarget(_txt)
-            if _target != self._popup.target_data:
-                self._timeCb(None) #we remove the popup
-                self.showWarning(_target)
+            self.showWarning(target)
+        elif target != self._popup.target_data:
+            self._timeCb(None) #we remove the popup
+            self.showWarning(target)
 
         self._timer.schedule(2000)
 
         #if keycode == KEY_ENTER and not self.visible:
         if keycode == KEY_ENTER:
             if _txt:
-                if _txt.startswith('@'):
-                    self.host.bridge.call('sendMblog', None, self.getText())
-                elif self._selected_cache == None:
-                    self.host.bridge.call('setStatus', None, _txt)
-                elif isinstance(self._selected_cache, ChatPanel):
-                    _chat = self._selected_cache
-                    mess_type = "groupchat" if _chat.type=='group' else "chat"
-                    self.host.bridge.call('sendMessage', None, str(_chat.target), _txt, '', mess_type)
+                target_hook, _type, msg = target
+                if target_hook:
+                    parsed_txt, data = target_hook
+                    if _type == "PUBLIC":
+                        self.host.bridge.call("sendMblog", None, "PUBLIC", None, parsed_txt)
+                    elif _type == "GROUP":
+                        self.host.bridge.call("sendMblog", None, "GROUP", data, parsed_txt)
+                    elif _type == "STATUS":
+                        self.host.bridge.call('setStatus', None, parsed_txt)
+                    else:
+                        print "ERROR: Unknown target hook type"
+                else: #we send the message to the selected target
+                    self._selected_cache.onTextEntered(_txt)
             self.setText('')
             self._timeCb(None) #we remove the popup
             sender.cancelKey()
@@ -246,6 +268,8 @@
 
 
 class MicroblogPanel(base_widget.LiberviaWidget):
+    warning_msg_public = "This message will be PUBLIC and everybody will be able to see it, even people you don't know"
+    warning_msg_group = "This message will be published for all the people of the group <span class='warningTarget'>%s</span>"
 
     def __init__(self, host, accepted_groups):
         """Panel used to show microblog
@@ -281,6 +305,22 @@
         host.bridge.call('getMassiveLastMblogs', _new_panel.massiveInsert, 'ALL', [], 10)
         return _new_panel
 
+    def getWarningData(self):
+        if not self.accepted_groups:
+            # we have a meta MicroblogPanel, we publish publicly
+            return ("PUBLIC", self.warning_msg_public)
+        else:
+            # we only accept one group at the moment
+            # FIXME: manage several groups
+            return ("GROUP", self.warning_msg_group %  self.accepted_groups[0])
+
+    def onTextEntered(self, text):
+        if not self.accepted_groups:
+            self.host.bridge.call("sendMblog", None, "PUBLIC", None, text)
+        else:
+            # FIXME: manage several groups
+            self.host.bridge.call("sendMblog", None, "GROUP", self.accepted_groups[0], text)
+
     def accept_all(self):
         return not self.accepted_groups #we accept every microblog only if we are not filtering by groups
 
@@ -486,6 +526,19 @@
         _new_panel.historyPrint()
         return _new_panel
 
+    def getWarningData(self):
+        if self.type not in ["one2one", "group"]:
+            raise Exception("Unmanaged type !")
+        if self.type == "one2one":
+            msg = "This message will be sent to your contact <span class='warningTarget'>%s</span>" % self.target
+        elif self.type == "group":
+            msg = "This message will be sent to all the participants of the multi-user room <span class='warningTarget'>%s</span>" % self.target
+        return ("ONE2ONE" if self.type == "one2one" else "GROUP", msg)
+
+    def onTextEntered(self, text):
+        mess_type = "groupchat" if self.type=='group' else "chat"
+        self.host.bridge.call('sendMessage', None, str(self.target), text, '', mess_type)
+
     def onQuit(self):
         base_widget.LiberviaWidget.onQuit(self)
         if self.type == 'group':
--- a/libervia.tac	Mon Mar 25 14:09:10 2013 +0100
+++ b/libervia.tac	Sun Apr 07 22:33:55 2013 +0200
@@ -185,28 +185,28 @@
         self.sat_host.bridge.setPresence('', '', 0, {'':status}, profile)
 
     
-    def jsonrpc_sendMessage(self, to_jid, msg, subject, type):
+    def jsonrpc_sendMessage(self, to_jid, msg, subject, _type):
         """send message"""
         profile = ISATSession(self.session).profile
-        return self.sat_host.bridge.sendMessage(to_jid, msg, subject, type, profile)
+        return self.sat_host.bridge.sendMessage(to_jid, msg, subject, _type, profile)
 
-    def jsonrpc_sendMblog(self, raw_text):
-        """Parse raw_text of the microblog box, and send message consequently"""
+    def jsonrpc_sendMblog(self, _type, dest, text):
+        """ Send microblog message
+        @param _type: one of "PUBLIC", "GROUP"
+        @param dest: destinees (list of groups, ignored for "PUBLIC")
+        @param text: microblog's text
+        """
         profile = ISATSession(self.session).profile
-        match = re.match(r'@(.+?): *(.*$)', raw_text)
-        if match:
-            recip = match.group(1)
-            text = match.group(2)
-            #if recip == '@' and text:
-            #    #This text if for the public microblog
-            #    return self.sat_host.bridge.sendPersonalEvent("MICROBLOG", {'content':text}, profile)
-            if recip == '@' and text:
+        if _type in ("PUBLIC", "GROUP") and text:
+            if _type == "PUBLIC":
                 #This text if for the public microblog
                 print "sending public blog"
                 return self.sat_host.bridge.sendGroupBlog("PUBLIC", [], text, profile)
             else:
                 print "sending group blog"
-                return self.sat_host.bridge.sendGroupBlog("GROUP", [recip], text, profile)
+                return self.sat_host.bridge.sendGroupBlog("GROUP", [dest], text, profile)
+        else:
+            raise Exception("Invalid data") 
     
     def jsonrpc_getLastMblogs(self, publisher_jid, max_item):
         """Get last microblogs posted by a contact