summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/connection.py1
-rw-r--r--src/core.py20
-rw-r--r--src/tabs.py62
-rw-r--r--src/theming.py6
4 files changed, 81 insertions, 8 deletions
diff --git a/src/connection.py b/src/connection.py
index 1079b5a6..74a21cdb 100644
--- a/src/connection.py
+++ b/src/connection.py
@@ -59,6 +59,7 @@ class Connection(sleekxmpp.ClientXMPP):
self.register_plugin('xep_0092', pconfig=info)
if config.get('send_time', 'true') == 'true':
self.register_plugin('xep_0202')
+ self.register_plugin('xep_0224')
def start(self):
# TODO, try multiple servers
diff --git a/src/core.py b/src/core.py
index 9b74c1a5..4364734e 100644
--- a/src/core.py
+++ b/src/core.py
@@ -194,6 +194,7 @@ class Core(object):
self.xmpp.add_event_handler("chatstate_paused", self.on_chatstate_paused)
self.xmpp.add_event_handler("chatstate_gone", self.on_chatstate_gone)
self.xmpp.add_event_handler("chatstate_inactive", self.on_chatstate_inactive)
+ self.xmpp.add_event_handler("attention", self.on_attention)
self.xmpp.register_handler(Callback('ALL THE STANZAS', connection.MatchAll(None), self.incoming_stanza))
self.timed_events = set()
@@ -503,6 +504,21 @@ class Core(object):
tab.input.refresh()
self.doupdate()
+ def on_attention(self, message):
+ jid_from = message['from']
+ self.information('%s requests your attention!' % jid_from, 'Info')
+ for tab in self.tabs:
+ if tab.get_name() == jid_from:
+ tab.state = 'attention'
+ self.refresh_tab_win()
+ return
+ for tab in self.tabs:
+ if tab.get_name() == jid_from.bare:
+ tab.state = 'attention'
+ self.refresh_tab_win()
+ return
+ self.information('%s tab not found.' % jid_from, 'Error')
+
def open_new_form(self, form, on_cancel, on_send, **kwargs):
"""
Open a new tab containing the form
@@ -1076,6 +1092,10 @@ class Core(object):
- A Muc with any new message
"""
for tab in self.tabs:
+ if tab.state == 'attention':
+ self.command_win('%s' % tab.nb)
+ return
+ for tab in self.tabs:
if tab.state == 'private':
self.command_win('%s' % tab.nb)
return
diff --git a/src/tabs.py b/src/tabs.py
index 7df200b0..9bc6e24c 100644
--- a/src/tabs.py
+++ b/src/tabs.py
@@ -67,7 +67,7 @@ STATE_COLORS = {
'private': lambda: get_theme().COLOR_TAB_PRIVATE,
'normal': lambda: get_theme().COLOR_TAB_NORMAL,
'current': lambda: get_theme().COLOR_TAB_CURRENT,
-# 'attention': lambda: get_theme().COLOR_TAB_ATTENTION,
+ 'attention': lambda: get_theme().COLOR_TAB_ATTENTION,
}
VERTICAL_STATE_COLORS = {
@@ -77,7 +77,7 @@ VERTICAL_STATE_COLORS = {
'private': lambda: get_theme().COLOR_VERTICAL_TAB_PRIVATE,
'normal': lambda: get_theme().COLOR_VERTICAL_TAB_NORMAL,
'current': lambda: get_theme().COLOR_VERTICAL_TAB_CURRENT,
-# 'attention': lambda: get_theme().COLOR_VERTICAL_TAB_ATTENTION,
+ 'attention': lambda: get_theme().COLOR_VERTICAL_TAB_ATTENTION,
}
@@ -88,7 +88,7 @@ STATE_PRIORITY = {
'message': 1,
'highlight': 2,
'private': 2,
-# 'attention': 3
+ 'attention': 3
}
class Tab(object):
@@ -156,7 +156,7 @@ class Tab(object):
log.debug("Invalid value for tab state: %s", value)
elif STATE_PRIORITY[value] < STATE_PRIORITY[self._state] and \
value != 'current':
- log.debug("Did not set status because of lower priority, asked: %s, kept: %s", (value, self.state))
+ log.debug("Did not set status because of lower priority, asked: %s, kept: %s", (value, self._state))
else:
self._state = value
@@ -349,6 +349,7 @@ class ChatTab(Tab):
# if that’s None, then no paused chatstate was sent recently
# if that’s a weakref returning None, then a paused chatstate was sent
# since the last input
+ self.remote_supports_attention = False
self.key_func['M-v'] = self.move_separator
self.key_func['M-/'] = self.last_words_completion
self.key_func['^M'] = self.on_enter
@@ -495,6 +496,7 @@ class ChatTab(Tab):
def command_say(self, line):
raise NotImplementedError
+
class MucTab(ChatTab):
"""
The tab containing a multi-user-chat room.
@@ -1359,6 +1361,7 @@ class PrivateTab(ChatTab):
self._text_buffer.add_window(self.text_win)
self.info_header = windows.PrivateInfoWin()
self.input = windows.MessageInput()
+ self.check_attention()
# keys
self.key_func['^I'] = self.completion
# commands
@@ -1379,7 +1382,7 @@ class PrivateTab(ChatTab):
def completion(self):
self.complete_commands(self.input)
- def command_say(self, line):
+ def command_say(self, line, attention=False):
if not self.on:
return
msg = self.core.xmpp.make_message(self.get_name())
@@ -1396,12 +1399,35 @@ class PrivateTab(ChatTab):
if config.get_by_tabname('send_chat_states', 'true', self.general_jid, True) == 'true' and self.remote_wants_chatstates is not False:
needed = 'inactive' if self.core.status.show in ('xa', 'away') else 'active'
msg['chat_state'] = needed
+ if attention and self.remote_supports_attention:
+ msg['attention'] = True
self.core.events.trigger('private_say_after', msg, self)
msg.send()
self.cancel_paused_delay()
self.text_win.refresh()
self.input.refresh()
+ def command_attention(self, message=''):
+ if message is not '':
+ self.command_say(message, attention=True)
+ else:
+ msg = self.core.xmpp.make_message(self.get_name())
+ msg['type'] = 'chat'
+ msg['attention'] = True
+ msg.send()
+
+ def check_attention(self):
+ self.core.xmpp.plugin['xep_0030'].get_info(jid=self.get_name(), block=False, timeout=5, callback=self.on_attention_checked)
+
+ def on_attention_checked(self, iq):
+ if 'urn:xmpp:attention:0' in iq['disco_info'].get_features():
+ self.core.information('Attention is supported!', 'Info')
+ self.remote_supports_attention = True
+ self.commands['attention'] = (self.command_attention, _('Usage: /attention [message]\nAttention: Require the attention of the contact. Can also send a message along with the attention.'), None)
+ else:
+ self.core.information('Attention is not supported. :(', 'Info')
+ self.remote_supports_attention = False
+
def command_unquery(self, arg):
"""
/unquery
@@ -2096,6 +2122,7 @@ class ConversationTab(ChatTab):
self.upper_bar = windows.ConversationStatusMessageWin()
self.info_header = windows.ConversationInfoWin()
self.input = windows.MessageInput()
+ self.check_attention()
# keys
self.key_func['^I'] = self.completion
# commands
@@ -2125,7 +2152,7 @@ class ConversationTab(ChatTab):
def completion(self):
self.complete_commands(self.input)
- def command_say(self, line):
+ def command_say(self, line, attention=False):
msg = self.core.xmpp.make_message(self.get_name())
msg['type'] = 'chat'
msg['body'] = line
@@ -2141,6 +2168,8 @@ class ConversationTab(ChatTab):
if config.get_by_tabname('send_chat_states', 'true', self.general_jid, True) == 'true' and self.remote_wants_chatstates is not False:
needed = 'inactive' if self.core.status.show in ('xa', 'away') else 'active'
msg['chat_state'] = needed
+ if attention and self.remote_supports_attention:
+ msg['attention'] = True
self.core.events.trigger('conversation_say_after', msg, self)
msg.send()
logger.log_message(JID(self.get_name()).bare, self.core.own_nick, line)
@@ -2160,6 +2189,27 @@ class ConversationTab(ChatTab):
self.refresh()
self.core.doupdate()
+ def command_attention(self, message=''):
+ if message is not '':
+ self.command_say(message, attention=True)
+ else:
+ msg = self.core.xmpp.make_message(self.get_name())
+ msg['type'] = 'chat'
+ msg['attention'] = True
+ msg.send()
+
+ def check_attention(self):
+ self.core.xmpp.plugin['xep_0030'].get_info(jid=self.get_name(), block=False, timeout=5, callback=self.on_attention_checked)
+
+ def on_attention_checked(self, iq):
+ if 'urn:xmpp:attention:0' in iq['disco_info'].get_features():
+ self.core.information('Attention is supported!', 'Info')
+ self.remote_supports_attention = True
+ self.commands['attention'] = (self.command_attention, _('Usage: /attention [message]\nAttention: Require the attention of the contact. Can also send a message along with the attention.'), None)
+ else:
+ self.core.information('Attention is not supported. :(', 'Info')
+ self.remote_supports_attention = False
+
def command_unquery(self, arg):
self.core.close_tab()
diff --git a/src/theming.py b/src/theming.py
index 25188f81..fba33366 100644
--- a/src/theming.py
+++ b/src/theming.py
@@ -124,15 +124,17 @@ class Theme(object):
COLOR_TAB_NORMAL = (7, 4)
COLOR_TAB_CURRENT = (7, 6)
COLOR_TAB_NEW_MESSAGE = (7, 5)
- COLOR_TAB_HIGHLIGHT = (7, 1)
+ COLOR_TAB_HIGHLIGHT = (7, 3)
COLOR_TAB_PRIVATE = (7, 2)
+ COLOR_TAB_ATTENTION = (7, 1)
COLOR_TAB_DISCONNECTED = (7, 8)
COLOR_VERTICAL_TAB_NORMAL = (4, -1)
COLOR_VERTICAL_TAB_CURRENT = (7, 4)
COLOR_VERTICAL_TAB_NEW_MESSAGE = (5, -1)
- COLOR_VERTICAL_TAB_HIGHLIGHT = (1, -1)
+ COLOR_VERTICAL_TAB_HIGHLIGHT = (3, -1)
COLOR_VERTICAL_TAB_PRIVATE = (2, -1)
+ COLOR_VERTICAL_TAB_ATTENTION = (1, -1)
COLOR_VERTICAL_TAB_DISCONNECTED = (8, -1)
# Nickname colors