Commit 760645f5 authored by Philipp Hörist's avatar Philipp Hörist

Improve MUC notifications

- Play sound for received messages, if notify for all messages is activated
- Send system notifications on MUC messages
- Make notify for all the default in private MUCs

Fixes #9383
parent dac53707
Pipeline #2844 passed with stages
in 3 minutes and 47 seconds
......@@ -905,8 +905,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
if kind == 'incoming':
if not self.type_id == message_control.TYPE_GC or \
app.config.get('notify_on_all_muc_messages') or \
app.config.get_per('rooms', jid, 'notify_on_all_messages') or \
app.config.notify_for_muc(jid) or \
'marked' in other_tags_for_text:
# it's a normal message, or a muc message with want to be
# notified about if quitting just after
......@@ -482,7 +482,7 @@ class Config:
'contact_disconnected': [False, 'disconnected.wav'],
'message_sent': [False, 'sent.wav'],
'muc_message_highlight': [True, 'gc_message1.wav', _('Sound to play when a group chat message contains one of the words in muc_highlight_words, or when a group chat message contains your nickname.')],
'muc_message_received': [False, 'gc_message2.wav', _('Sound to play when any MUC message arrives.')],
'muc_message_received': [True, 'gc_message2.wav', _('Sound to play when any MUC message arrives.')],
proxies_default = {
......@@ -638,13 +638,15 @@ class Config:
obj[subname] = value
def get_per(self, optname, key=None, subname=None): # per_group_of_option
def get_per(self, optname, key=None, subname=None, default=None): # per_group_of_option
if optname not in self.__options_per_key:
return None
dict_ = self.__options_per_key[optname][1]
if not key:
return list(dict_.keys())
if key not in dict_:
if default is not None:
return default
if subname in self.__options_per_key[optname][0]:
return self.__options_per_key[optname][0][subname][1]
return None
......@@ -712,6 +714,11 @@ class Config:
return (account not in no_log_for) and (jid not in no_log_for)
def notify_for_muc(self, room):
all_ = self.get('notify_on_all_muc_messages')
room = self.get_per('rooms', room, 'notify_on_all_messages')
return all_ or room
def _init_options(self):
for opt in self.__options[0]:
self.__options[1][opt] = self.__options[0][opt][Option.VAL]
......@@ -1036,7 +1036,46 @@ class NotificationEvent(nec.NetworkIncomingEvent):
self.do_sound = False
self.do_popup = False
self.control = app.interface.msg_win_mgr.search_control(
msg_obj.jid, self.account)
if self.control is not None:
self.control_focused = self.control.has_focus()
if app.config.get('notify_on_new_message'):
notify_for_muc = (app.config.notify_for_muc(self.jid) or
sound == 'highlight')
if not notify_for_muc:
self.do_popup = False
elif self.control_focused:
self.do_popup = False
elif app.config.get('autopopupaway'):
# always show notification
self.do_popup = True
elif app.connections[].connected in (2, 3):
# we're online or chat
self.do_popup = True
self.popup_msg_type = 'gc_msg'
self.popup_event_type = _('New Group Chat Message')
if app.config.get('notification_preview_message'):
self.popup_text = msg_obj.msgtxt
type_events = ['printed_marked_gc_msg', 'printed_gc_msg']
count = len(, self.jid, type_events))
contact = app.contacts.get_contact(self.account, self.jid)
self.popup_title = i18n.ngettext(
'New message from %(nickname)s',
'%(n_msgs)i unread messages in %(groupchat_name)s',
count) % {'nickname': self.base_event.nick,
'n_msgs': count,
'groupchat_name': contact.get_shown_name()}
def handle_incoming_pres_event(self, pres_obj):
if app.jid_is_transport(pres_obj.jid):
......@@ -332,6 +332,16 @@ class Events:
return events_list
def get_all_events(self, types=None):
accounts = self._events.keys()
events = []
for account in accounts:
for jid in self._events[account]:
for event in self._events[account][jid]:
if types is None or event.type_ in types:
return events
def get_first_event(self, account=None, jid=None, type_=None):
Return the first event of type type_ if given
......@@ -375,8 +375,11 @@ class GroupchatControl(ChatControlBase):
act.connect('change-state', self._on_minimize)
# Enable notify on all for private rooms
members_only = muc_caps_cache.supports(,
value = app.config.get_per(
'rooms',, 'notify_on_all_messages')
'rooms',, 'notify_on_all_messages', members_only)
act = Gio.SimpleAction.new_stateful(
'notify-on-message-' + self.control_id,
......@@ -1294,8 +1297,7 @@ class GroupchatControl(ChatControlBase):
def get_nb_unread(self):
type_events = ['printed_marked_gc_msg']
if app.config.get('notify_on_all_muc_messages') or \
app.config.get_per('rooms', self.room_jid, 'notify_on_all_messages'):
if app.config.notify_for_muc(self.room_jid):
nb = len(, self.room_jid,
......@@ -1314,25 +1316,30 @@ class GroupchatControl(ChatControlBase):
Returns a 2-Tuple. The first says whether or not to highlight the text,
the second, what sound to play
highlight, sound = (None, None)
highlight, sound = None, None
notify = app.config.notify_for_muc(self.room_jid)
message_sound_enabled = app.config.get_per('soundevents',
# Are any of the defined highlighting words in the text?
if self.needs_visual_notification(text):
highlight = True
if app.config.get_per('soundevents', 'muc_message_highlight',
if app.config.get_per('soundevents',
sound = 'highlight'
# Do we play a sound on every muc message?
elif app.config.get_per('soundevents', 'muc_message_received', \
elif notify and message_sound_enabled:
sound = 'received'
# Is it a history message? Don't want sound-floods when we join.
if tim is not None and time.mktime(time.localtime()) - tim > 1:
sound = None
return (highlight, sound)
return highlight, sound
def check_and_possibly_add_focus_out_line(self):
......@@ -111,7 +111,8 @@ class Notification:
if event.type_ == 'gc-invitation':
self._withdraw('gc-invitation', event.account, event.room_jid)
if event.type_ in ('normal', 'printed_chat', 'chat',
'printed_pm', 'pm'):
'printed_pm', 'pm', 'printed_marked_gc_msg',
self._withdraw('new-message', event.account, event.jid)
def _nec_our_status(self, obj):
......@@ -164,6 +165,7 @@ class Notification:
if event_type in (
_('Contact Signed In'), _('Contact Signed Out'),
_('New Message'), _('New Single Message'), _('New Private Message'),
_('New Group Chat Message'),
_('Contact Changed Status'), _('File Transfer Request'),
_('File Transfer Error'), _('File Transfer Completed'),
_('File Transfer Stopped'), _('Groupchat Invitation'),
......@@ -193,7 +195,8 @@ class Notification:
notif_id = self._make_id('connection-failed', account)
elif event_type in (_('New Message'),
_('New Single Message'),
_('New Private Message')):
_('New Private Message'),
_('New Group Chat Message')):
avatar = app.contacts.get_avatar(account, jid)
if avatar:
icon_pixbuf = avatar
......@@ -467,11 +467,8 @@ def get_show_in_systray(type_, jid):
Return True if this event must be shown in systray, else False
notify = app.config.get('notify_on_all_muc_messages')
notify_for_jid = app.config.get_per(
'rooms', jid, 'notify_on_all_messages')
if type_ == 'printed_gc_msg' and not notify and not notify_for_jid:
notify = app.config.notify_for_muc(jid)
if type_ == 'printed_gc_msg' and not notify:
# it's not an highlighted message, don't show in systray
return False
return app.config.get('trayicon_notification_on_events')
......@@ -490,10 +490,9 @@ class MessageWindow:
unread = 0
for ctrl in self.controls():
if ctrl.type_id == message_control.TYPE_GC and not \
app.config.get('notify_on_all_muc_messages') and not \
app.config.get_per('rooms', ctrl.room_jid,
'notify_on_all_messages') and not ctrl.attention_flag:
if (ctrl.type_id == message_control.TYPE_GC and not
app.config.notify_for_muc(ctrl.room_jid) and not
# count only pm messages
unread += ctrl.get_nb_unread_pm()
......@@ -509,10 +508,8 @@ class MessageWindow:
if control.type_id == message_control.TYPE_GC:
name = control.room_jid.split('@')[0]
urgent = control.attention_flag or \
app.config.get('notify_on_all_muc_messages') or \
app.config.get_per('rooms', control.room_jid,
urgent = (control.attention_flag or
name =
if control.resource:
......@@ -2520,10 +2520,10 @@ class RosterWindow:
# check if we have unread messages
unread =
if not app.config.get('notify_on_all_muc_messages'):
unread_not_to_notify =
unread -= unread_not_to_notify
for event in['printed_gc_msg']):
if not app.config.notify_for_muc(event.jid):
unread -= 1
# check if we have recent messages
recent = False
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment