Mercurial > libervia-backend
comparison frontends/src/quick_frontend/quick_app.py @ 1972:02d21a589be2
quick_frontend, primitivus: notifications refactoring
replaced old "alerts" system by a more generic one which use listeners and can activate callbacks on notification click.
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 27 Jun 2016 22:36:22 +0200 |
parents | 200cd707a46d |
children | 19b9d3f8a6c7 |
comparison
equal
deleted
inserted
replaced
1971:9421e721d5e2 | 1972:02d21a589be2 |
---|---|
32 from sat_frontends.quick_frontend import quick_contact_list | 32 from sat_frontends.quick_frontend import quick_contact_list |
33 from sat_frontends.quick_frontend.constants import Const as C | 33 from sat_frontends.quick_frontend.constants import Const as C |
34 | 34 |
35 import sys | 35 import sys |
36 from collections import OrderedDict | 36 from collections import OrderedDict |
37 import time | |
37 | 38 |
38 try: | 39 try: |
39 # FIXME: to be removed when an acceptable solution is here | 40 # FIXME: to be removed when an acceptable solution is here |
40 unicode('') # XXX: unicode doesn't exist in pyjamas | 41 unicode('') # XXX: unicode doesn't exist in pyjamas |
41 except (TypeError, AttributeError): # Error raised is not the same depending on pyjsbuild options | 42 except (TypeError, AttributeError): # Error raised is not the same depending on pyjsbuild options |
49 cache_keys_to_get = ['avatar'] | 50 cache_keys_to_get = ['avatar'] |
50 | 51 |
51 def __init__(self, profile): | 52 def __init__(self, profile): |
52 self.profile = profile | 53 self.profile = profile |
53 self.whoami = None | 54 self.whoami = None |
54 self.data = {} | 55 self.notifications = {} # key: bare jid or '' for general, value: notif data |
55 | |
56 def __getitem__(self, key): | |
57 return self.data[key] | |
58 | |
59 def __setitem__(self, key, value): | |
60 self.data[key] = value | |
61 | 56 |
62 def plug(self): | 57 def plug(self): |
63 """Plug the profile to the host""" | 58 """Plug the profile to the host""" |
64 # we get the essential params | 59 # we get the essential params |
65 self.bridge.asyncGetParamA("JabberID", "Connection", profile_key=self.profile, | 60 self.bridge.asyncGetParamA("JabberID", "Connection", profile_key=self.profile, |
266 quick_games.Quiz.registerSignals(self) | 261 quick_games.Quiz.registerSignals(self) |
267 quick_games.Radiocol.registerSignals(self) | 262 quick_games.Radiocol.registerSignals(self) |
268 | 263 |
269 self.current_action_ids = set() # FIXME: to be removed | 264 self.current_action_ids = set() # FIXME: to be removed |
270 self.current_action_ids_cb = {} # FIXME: to be removed | 265 self.current_action_ids_cb = {} # FIXME: to be removed |
266 self._notif_id = 0 | |
267 self._notifications = OrderedDict() | |
271 self.media_dir = self.bridge.getConfig('', 'media_dir') | 268 self.media_dir = self.bridge.getConfig('', 'media_dir') |
272 self.features = None | 269 self.features = None |
273 | 270 |
274 @property | 271 @property |
275 def current_profile(self): | 272 def current_profile(self): |
281 | 278 |
282 @property | 279 @property |
283 def visible_widgets(self): | 280 def visible_widgets(self): |
284 """widgets currently visible (must be implemented by frontend)""" | 281 """widgets currently visible (must be implemented by frontend)""" |
285 raise NotImplementedError | 282 raise NotImplementedError |
286 | |
287 @property | |
288 def alerts_count(self): | |
289 """Count the over whole alerts for all contact lists""" | |
290 # FIXME | |
291 # return sum([sum(clist._alerts.values()) for clist in self.contact_lists.values()]) | |
292 | 283 |
293 def registerSignal(self, function_name, handler=None, iface="core", with_profile=True): | 284 def registerSignal(self, function_name, handler=None, iface="core", with_profile=True): |
294 """Register a handler for a signal | 285 """Register a handler for a signal |
295 | 286 |
296 @param function_name (str): name of the signal to handle | 287 @param function_name (str): name of the signal to handle |
328 args: (entity, avatar file, profile) | 319 args: (entity, avatar file, profile) |
329 - nick: called when nick data is updated | 320 - nick: called when nick data is updated |
330 args: (entity, new_nick, profile) | 321 args: (entity, new_nick, profile) |
331 - presence: called when a presence is received | 322 - presence: called when a presence is received |
332 args: (entity, show, priority, statuses, profile) | 323 args: (entity, show, priority, statuses, profile) |
324 - notification: called when a new notification is emited | |
325 args: (entity, notification_data, profile) | |
326 - notification_clear: called when notifications are cleared | |
327 args: (entity, type_, profile) | |
333 - menu: called when a menu item is added or removed | 328 - menu: called when a menu item is added or removed |
334 args: (type_, path, path_i18n, item) were values are: | 329 args: (type_, path, path_i18n, item) were values are: |
335 type_: same as in [sat.core.sat_main.SAT.importMenu] | 330 type_: same as in [sat.core.sat_main.SAT.importMenu] |
336 path: same as in [sat.core.sat_main.SAT.importMenu] | 331 path: same as in [sat.core.sat_main.SAT.importMenu] |
337 path_i18n: translated path (or None if the item is removed) | 332 path_i18n: translated path (or None if the item is removed) |
493 contact_list.setContact(from_jid) | 488 contact_list.setContact(from_jid) |
494 | 489 |
495 # we display the message in the widget | 490 # we display the message in the widget |
496 | 491 |
497 chat_widget.messageNew(uid, timestamp, from_jid, target, msg, subject, type_, extra, profile) | 492 chat_widget.messageNew(uid, timestamp, from_jid, target, msg, subject, type_, extra, profile) |
498 | |
499 # ContactList alert | |
500 if not from_me: | |
501 visible = False | |
502 for widget in self.visible_widgets: | |
503 if isinstance(widget, quick_chat.QuickChat) and widget.manageMessage(from_jid, type_): | |
504 visible = True | |
505 break | |
506 if visible: # FIXME: à virer gof: | |
507 if self.isHidden(): # the window is hidden | |
508 self.updateAlertsCounter(extra_inc=1) | |
509 else: | |
510 contact_list.addAlert(from_jid.bare if type_ == C.MESS_TYPE_GROUPCHAT else from_jid) | |
511 | 493 |
512 def messageSend(self, to_jid, message, subject=None, mess_type="auto", extra=None, callback=None, errback=None, profile_key=C.PROF_KEY_NONE): | 494 def messageSend(self, to_jid, message, subject=None, mess_type="auto", extra=None, callback=None, errback=None, profile_key=C.PROF_KEY_NONE): |
513 if subject is None: | 495 if subject is None: |
514 subject = {} | 496 subject = {} |
515 if extra is None: | 497 if extra is None: |
600 # widget.update(occupant) | 582 # widget.update(occupant) |
601 # elif from_jid.bare == widget.target.bare: # roster contact or MUC occupant | 583 # elif from_jid.bare == widget.target.bare: # roster contact or MUC occupant |
602 # contact_list.setCache(from_jid, 'chat_state', to_display) | 584 # contact_list.setCache(from_jid, 'chat_state', to_display) |
603 # widget.update(from_jid) | 585 # widget.update(from_jid) |
604 | 586 |
587 def notify(self, type_, entity=None, message=None, subject=None, callback=None, cb_args=None, widget=None, profile=C.PROF_KEY_NONE): | |
588 """Trigger an event notification | |
589 | |
590 @param type_(unicode): notifation kind, | |
591 one of C.NOTIFY_* constant or any custom type specific to frontend | |
592 @param entity(jid.JID, None): entity involved in the notification | |
593 if entity is in contact list, a indicator may be added in front of it | |
594 @param message(unicode, None): message of the notification | |
595 @param subject(unicode, None): subject of the notification | |
596 @param callback(callable, None): method to call when notification is selected | |
597 @param cb_args(list, None): list of args for callback | |
598 @param widget(object, None): widget where the notification happened | |
599 """ | |
600 notif_dict = self.profiles[profile].notifications | |
601 key = '' if entity is None else entity.bare | |
602 type_notifs = notif_dict.setdefault(key, {}).setdefault(type_, []) | |
603 notif_data = { | |
604 'id': self._notif_id, | |
605 'time': time.time(), | |
606 'entity': entity, | |
607 'callback': callback, | |
608 'cb_args': cb_args, | |
609 'message': message, | |
610 'subject': subject, | |
611 } | |
612 if widget is not None: | |
613 notif_data[widget] = widget | |
614 type_notifs.append(notif_data) | |
615 self._notifications[self._notif_id] = notif_data | |
616 self.callListeners('notification', entity, notif_data, profile=profile) | |
617 | |
618 def getNotifs(self, entity, type_=None, profile=C.PROF_KEY_NONE): | |
619 """return notifications for given entity | |
620 | |
621 @param entity(jid.JID, None): bare jid of the entity to check | |
622 None to get general notifications | |
623 @param type_(unicode, None): notification type to filter | |
624 None to get all notifications | |
625 @return (list[dict]): list of notifications | |
626 """ | |
627 notif_dict = self.profiles[profile].notifications | |
628 key = '' if entity is None else entity.bare | |
629 key_notifs = notif_dict.setdefault(key, {}) | |
630 if type_ is not None: | |
631 return key_notifs.get(type_, []) | |
632 ret = [] | |
633 for notifs_list in key_notifs.itervalues(): | |
634 ret.extend(notifs_list) | |
635 return ret | |
636 | |
637 def clearNotifs(self, entity, type_=None, profile=C.PROF_KEY_NONE): | |
638 """return notifications for given entity | |
639 | |
640 @param entity(jid.JID, None): bare jid of the entity to check | |
641 None to clear general notifications (but keep entities ones) | |
642 @param type_(unicode, None): notification type to filter | |
643 None to clear all notifications | |
644 @return (list[dict]): list of notifications | |
645 """ | |
646 notif_dict = self.profiles[profile].notifications | |
647 key = '' if entity is None else entity.bare | |
648 try: | |
649 if type_ is None: | |
650 del notif_dict[key] | |
651 else: | |
652 del notif_dict[key][type_] | |
653 except KeyError: | |
654 return | |
655 self.callListeners('notificationsClear', entity, type_, profile=profile) | |
656 | |
605 def psEventHandler(self, category, service_s, node, event_type, data, profile): | 657 def psEventHandler(self, category, service_s, node, event_type, data, profile): |
606 """Called when a PubSub event is received. | 658 """Called when a PubSub event is received. |
607 | 659 |
608 @param category(unicode): event category (e.g. "PEP", "MICROBLOG") | 660 @param category(unicode): event category (e.g. "PEP", "MICROBLOG") |
609 @param service_s (unicode): pubsub service | 661 @param service_s (unicode): pubsub service |
686 | 738 |
687 @return bool | 739 @return bool |
688 """ | 740 """ |
689 raise NotImplementedError | 741 raise NotImplementedError |
690 | 742 |
691 def updateAlertsCounter(self, extra_inc=0): | |
692 """Update the over whole alerts counter. | |
693 | |
694 @param extra_inc (int): extra counter | |
695 """ | |
696 pass | |
697 | |
698 def paramUpdateHandler(self, name, value, namespace, profile): | 743 def paramUpdateHandler(self, name, value, namespace, profile): |
699 log.debug(_(u"param update: [%(namespace)s] %(name)s = %(value)s") % {'namespace': namespace, 'name': name, 'value': value}) | 744 log.debug(_(u"param update: [%(namespace)s] %(name)s = %(value)s") % {'namespace': namespace, 'name': name, 'value': value}) |
700 if (namespace, name) == ("Connection", "JabberID"): | 745 if (namespace, name) == ("Connection", "JabberID"): |
701 log.debug(_(u"Changing JID to %s") % value) | 746 log.debug(_(u"Changing JID to %s") % value) |
702 self.profiles[profile].whoami = jid.JID(value) | 747 self.profiles[profile].whoami = jid.JID(value) |