comparison browser_side/panels.py @ 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
comparison
equal deleted inserted replaced
200:0f5c2f799913 201:aa76793da353
85 except KeyError: 85 except KeyError:
86 print "WARNING: trying to remove an unknown key" 86 print "WARNING: trying to remove an unknown key"
87 87
88 88
89 def showWarning(self, target_data): 89 def showWarning(self, target_data):
90 type, target = target_data 90 target_hook, _type, msg = target_data
91 if type == "PUBLIC": 91 if _type == "NONE":
92 msg = "This message will be PUBLIC and everybody will be able to see it, even people you don't know" 92 return
93 if not msg:
94 print "WARNING: no msg set uniBox warning"
95 return
96 if _type == "PUBLIC":
93 style = "targetPublic" 97 style = "targetPublic"
94 elif type == "GROUP": 98 elif _type == "GROUP":
95 msg = "This message will be published for all the people of the group <span class='warningTarget'>%s</span>" % (target or '')
96 style = "targetGroup" 99 style = "targetGroup"
97 elif type == "STATUS": 100 elif _type == "STATUS":
98 msg = "This will be your new status message" 101 msg = "This will be your new status message"
99 style = "targetStatus" 102 style = "targetStatus"
100 elif type == "ONE2ONE": 103 elif _type == "ONE2ONE":
101 msg = "This message will be sent to your contact <span class='warningTarget'>%s</span>" % target
102 style = "targetOne2One" 104 style = "targetOne2One"
103 else: 105 else:
104 print "WARNING: undetermined target for this message" 106 print "ERROR: unknown message type"
105 return 107 return
106 contents = HTML(msg) 108 contents = HTML(msg)
107 109
108 self._popup = dialog.PopupPanelWrapper(autoHide=False, modal=False) 110 self._popup = dialog.PopupPanelWrapper(autoHide=False, modal=False)
109 self._popup.target_data = target_data 111 self._popup.target_data = target_data
113 self._popup.addStyleName(style) 115 self._popup.addStyleName(style)
114 116
115 left = 0 117 left = 0
116 top = 0 #max(0, self.getAbsoluteTop() - contents.getOffsetHeight() - 2) 118 top = 0 #max(0, self.getAbsoluteTop() - contents.getOffsetHeight() - 2)
117 self._popup.setPopupPosition(left, top) 119 self._popup.setPopupPosition(left, top)
118 self._popup.setPopupPosition(left, top)
119 self._popup.show() 120 self._popup.show()
120 121
121 def _timeCb(self, timer): 122 def _timeCb(self, timer):
122 if self._popup: 123 if self._popup:
123 self._popup.hide() 124 self._popup.hide()
124 del self._popup 125 del self._popup
125 self._popup = None 126 self._popup = None
126 127
127 def _getTarget(self, txt): 128 def _getTarget(self, txt):
128 """Say who will receive the messsage 129 """ Say who will receive the messsage
129 Return a tuple (target_type, target info)""" 130 @return: a tuple (selected, target_type, target info) with:
130 type = None 131 - 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))
131 target = None 132 - target_type: one of PUBLIC, GROUP, ONE2ONE, STATUS, MISC
132 if txt.startswith('@@: '): 133 - msg: HTML message which will appear in the privacy warning banner """
133 type = "PUBLIC" 134 target = self._selected_cache
135
136 def getSelectedOrStatus():
137 if target:
138 _type, msg = target.getWarningData()
139 target_hook = None # we use the selected widget, not a hook
140 else:
141 _type, msg = "STATUS", "This will be your new status message"
142 target_hook = (txt, None)
143 return (target_hook, _type, msg)
144
145 if not txt.startswith('@'):
146 target_hook, _type, msg = getSelectedOrStatus()
147 elif txt.startswith('@@: '):
148 _type = "PUBLIC"
149 msg = MicroblogPanel.warning_msg_public
150 target_hook = (txt[4:], None)
134 elif txt.startswith('@'): 151 elif txt.startswith('@'):
135 type = "GROUP"
136 _end = txt.find(': ') 152 _end = txt.find(': ')
137 if _end == -1: 153 if _end == -1:
138 type = "STATUS" 154 target_hook, _type, msg = getSelectedOrStatus()
139 else: 155 else:
140 target = txt[1:_end] #only one target group is managed for the moment 156 group = txt[1:_end] #only one target group is managed for the moment
141 if not target in self.host.contact_panel.getGroups(): 157 if not group or not group in self.host.contact_panel.getGroups():
142 target = None 158 # the group doesn't exists, we ignore the key
143 elif self._selected_cache == None: 159 group = None
144 type = "STATUS" 160 target_hook, _type, msg = getSelectedOrStatus()
145 elif isinstance(self._selected_cache, ChatPanel): 161 else:
146 type = "ONE2ONE" 162 _type = "GROUP"
147 target = str(self._selected_cache.target) 163 msg = MicroblogPanel.warning_msg_group % group
164 target_hook = (txt[_end+2:], group)
148 else: 165 else:
149 print "Unknown selected host:",self._selected_cache 166 print "ERROR: Unknown target"
150 type = "UNKNOWN" 167 target_hook, _type, msg = getSelectedOrStatus()
151 return (type, target) 168
169 return (target_hook, _type, msg)
152 170
153 def onBrowserEvent(self, event): 171 def onBrowserEvent(self, event):
154 #XXX: woraroung a pyjamas bug: self.currentEvent is not set 172 #XXX: woraroung a pyjamas bug: self.currentEvent is not set
155 # so the TextBox's cancelKey doens't work. This is a workaround 173 # so the TextBox's cancelKey doens't work. This is a workaround
156 # FIXME: fix the bug upstream 174 # FIXME: fix the bug upstream
157 self.currentEvent = event 175 self.currentEvent = event
158 TextArea.onBrowserEvent(self, event) 176 TextArea.onBrowserEvent(self, event)
159 177
160 def onKeyPress(self, sender, keycode, modifiers): 178 def onKeyPress(self, sender, keycode, modifiers):
161 _txt = self.getText() 179 _txt = self.getText()
180 target = self._getTarget(_txt)
162 if not self._popup: 181 if not self._popup:
163 self.showWarning(self._getTarget(_txt)) 182 self.showWarning(target)
164 else: 183 elif target != self._popup.target_data:
165 _target = self._getTarget(_txt) 184 self._timeCb(None) #we remove the popup
166 if _target != self._popup.target_data: 185 self.showWarning(target)
167 self._timeCb(None) #we remove the popup
168 self.showWarning(_target)
169 186
170 self._timer.schedule(2000) 187 self._timer.schedule(2000)
171 188
172 #if keycode == KEY_ENTER and not self.visible: 189 #if keycode == KEY_ENTER and not self.visible:
173 if keycode == KEY_ENTER: 190 if keycode == KEY_ENTER:
174 if _txt: 191 if _txt:
175 if _txt.startswith('@'): 192 target_hook, _type, msg = target
176 self.host.bridge.call('sendMblog', None, self.getText()) 193 if target_hook:
177 elif self._selected_cache == None: 194 parsed_txt, data = target_hook
178 self.host.bridge.call('setStatus', None, _txt) 195 if _type == "PUBLIC":
179 elif isinstance(self._selected_cache, ChatPanel): 196 self.host.bridge.call("sendMblog", None, "PUBLIC", None, parsed_txt)
180 _chat = self._selected_cache 197 elif _type == "GROUP":
181 mess_type = "groupchat" if _chat.type=='group' else "chat" 198 self.host.bridge.call("sendMblog", None, "GROUP", data, parsed_txt)
182 self.host.bridge.call('sendMessage', None, str(_chat.target), _txt, '', mess_type) 199 elif _type == "STATUS":
200 self.host.bridge.call('setStatus', None, parsed_txt)
201 else:
202 print "ERROR: Unknown target hook type"
203 else: #we send the message to the selected target
204 self._selected_cache.onTextEntered(_txt)
183 self.setText('') 205 self.setText('')
184 self._timeCb(None) #we remove the popup 206 self._timeCb(None) #we remove the popup
185 sender.cancelKey() 207 sender.cancelKey()
186 208
187 def onMouseUp(self, sender, x, y): 209 def onMouseUp(self, sender, x, y):
244 print "microblog entry selected (author=%s)" % self.author 266 print "microblog entry selected (author=%s)" % self.author
245 self._blog_panel.setSelectedEntry(self) 267 self._blog_panel.setSelectedEntry(self)
246 268
247 269
248 class MicroblogPanel(base_widget.LiberviaWidget): 270 class MicroblogPanel(base_widget.LiberviaWidget):
271 warning_msg_public = "This message will be PUBLIC and everybody will be able to see it, even people you don't know"
272 warning_msg_group = "This message will be published for all the people of the group <span class='warningTarget'>%s</span>"
249 273
250 def __init__(self, host, accepted_groups): 274 def __init__(self, host, accepted_groups):
251 """Panel used to show microblog 275 """Panel used to show microblog
252 @param accepted_groups: groups displayed in this panel, if empty, show all microblogs from all contacts 276 @param accepted_groups: groups displayed in this panel, if empty, show all microblogs from all contacts
253 """ 277 """
278 def createMeta(cls, host, item): 302 def createMeta(cls, host, item):
279 _new_panel = MicroblogPanel(host, []) #XXX: pyjamas doesn't support use of cls directly 303 _new_panel = MicroblogPanel(host, []) #XXX: pyjamas doesn't support use of cls directly
280 host.FillMicroblogPanel(_new_panel) 304 host.FillMicroblogPanel(_new_panel)
281 host.bridge.call('getMassiveLastMblogs', _new_panel.massiveInsert, 'ALL', [], 10) 305 host.bridge.call('getMassiveLastMblogs', _new_panel.massiveInsert, 'ALL', [], 10)
282 return _new_panel 306 return _new_panel
307
308 def getWarningData(self):
309 if not self.accepted_groups:
310 # we have a meta MicroblogPanel, we publish publicly
311 return ("PUBLIC", self.warning_msg_public)
312 else:
313 # we only accept one group at the moment
314 # FIXME: manage several groups
315 return ("GROUP", self.warning_msg_group % self.accepted_groups[0])
316
317 def onTextEntered(self, text):
318 if not self.accepted_groups:
319 self.host.bridge.call("sendMblog", None, "PUBLIC", None, text)
320 else:
321 # FIXME: manage several groups
322 self.host.bridge.call("sendMblog", None, "GROUP", self.accepted_groups[0], text)
283 323
284 def accept_all(self): 324 def accept_all(self):
285 return not self.accepted_groups #we accept every microblog only if we are not filtering by groups 325 return not self.accepted_groups #we accept every microblog only if we are not filtering by groups
286 326
287 def getEntries(self): 327 def getEntries(self):
483 _contact = JID(item) 523 _contact = JID(item)
484 host.contact_panel.setContactMessageWaiting(_contact.bare, False) 524 host.contact_panel.setContactMessageWaiting(_contact.bare, False)
485 _new_panel = ChatPanel(host, _contact) #XXX: pyjamas doesn't seems to support creating with cls directly 525 _new_panel = ChatPanel(host, _contact) #XXX: pyjamas doesn't seems to support creating with cls directly
486 _new_panel.historyPrint() 526 _new_panel.historyPrint()
487 return _new_panel 527 return _new_panel
528
529 def getWarningData(self):
530 if self.type not in ["one2one", "group"]:
531 raise Exception("Unmanaged type !")
532 if self.type == "one2one":
533 msg = "This message will be sent to your contact <span class='warningTarget'>%s</span>" % self.target
534 elif self.type == "group":
535 msg = "This message will be sent to all the participants of the multi-user room <span class='warningTarget'>%s</span>" % self.target
536 return ("ONE2ONE" if self.type == "one2one" else "GROUP", msg)
537
538 def onTextEntered(self, text):
539 mess_type = "groupchat" if self.type=='group' else "chat"
540 self.host.bridge.call('sendMessage', None, str(self.target), text, '', mess_type)
488 541
489 def onQuit(self): 542 def onQuit(self):
490 base_widget.LiberviaWidget.onQuit(self) 543 base_widget.LiberviaWidget.onQuit(self)
491 if self.type == 'group': 544 if self.type == 'group':
492 self.host.bridge.call('mucLeave', None, self.target.bare) 545 self.host.bridge.call('mucLeave', None, self.target.bare)