summaryrefslogtreecommitdiff
path: root/src/tabs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tabs')
-rw-r--r--src/tabs/__init__.py2
-rw-r--r--src/tabs/basetabs.py94
-rw-r--r--src/tabs/conversationtab.py36
-rw-r--r--src/tabs/privatetab.py37
4 files changed, 96 insertions, 73 deletions
diff --git a/src/tabs/__init__.py b/src/tabs/__init__.py
index 5f09bf38..eaf41a2f 100644
--- a/src/tabs/__init__.py
+++ b/src/tabs/__init__.py
@@ -1,4 +1,4 @@
-from . basetabs import Tab, ChatTab, GapTab
+from . basetabs import Tab, ChatTab, GapTab, OneToOneTab
from . basetabs import STATE_PRIORITY
from . rostertab import RosterInfoTab
from . muctab import MucTab, NS_MUC_USER
diff --git a/src/tabs/basetabs.py b/src/tabs/basetabs.py
index c472bd60..6fb8a329 100644
--- a/src/tabs/basetabs.py
+++ b/src/tabs/basetabs.py
@@ -433,9 +433,6 @@ class ChatTab(Tab):
self.name = jid
self.text_win = None
self._text_buffer = TextBuffer()
- self.remote_wants_chatstates = None # change this to True or False when
- # we know that the remote user wants chatstates, or not.
- # None means we don’t know yet, and we send only "active" chatstates
self.chatstate = None # can be "active", "composing", "paused", "gone", "inactive"
# We keep a weakref of the event that will set our chatstate to "paused", so that
# we can delete it or change it if we need to
@@ -443,7 +440,6 @@ 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
# Keeps the last sent message to complete it easily in completion_correct, and to replace it.
self.last_sent_message = None
self.key_func['M-v'] = self.move_separator
@@ -503,15 +499,6 @@ class ChatTab(Tab):
identifier=identifier,
jid=jid)
- def ack_message(self, msg_id):
- """
- Ack a message
- """
- new_msg = self._text_buffer.ack_message(msg_id)
- if new_msg:
- self.text_win.modify_message(msg_id, new_msg)
- self.core.refresh_window()
-
def modify_message(self, txt, old_id, new_id, user=None, jid=None, nickname=None):
self.log_message(txt, nickname, typ=1)
message = self._text_buffer.modify_message(txt, old_id, new_id, time=time, user=user, jid=jid)
@@ -709,3 +696,84 @@ class ChatTab(Tab):
def scroll_separator(self):
self.text_win.scroll_to_separator()
+class OneToOneTab(ChatTab):
+
+ def __init__(self, jid=''):
+ ChatTab.__init__(self, jid)
+
+ # change this to True or False when
+ # we know that the remote user wants chatstates, or not.
+ # None means we don’t know yet, and we send only "active" chatstates
+ self.remote_wants_chatstates = None
+ self.remote_supports_attention = False
+ self.remote_supports_receipts = True
+ self.check_features()
+
+ def ack_message(self, msg_id):
+ """
+ Ack a message
+ """
+ new_msg = self._text_buffer.ack_message(msg_id)
+ if new_msg:
+ self.text_win.modify_message(msg_id, new_msg)
+ self.core.refresh_window()
+
+ def check_features(self):
+ "check the features supported by the other party"
+ self.core.xmpp.plugin['xep_0030'].get_info(
+ jid=self.get_dest_jid(), block=False, timeout=5,
+ callback=self.features_checked)
+
+ def command_attention(self, message=''):
+ "/attention [message]"
+ if message is not '':
+ self.command_say(message, attention=True)
+ else:
+ msg = self.core.xmpp.make_message(self.get_dest_jid())
+ msg['type'] = 'chat'
+ msg['attention'] = True
+ msg.send()
+
+ def command_say(self, line, correct=False, attention=False):
+ pass
+
+ def _feature_attention(self, features):
+ "Check for the 'attention' features"
+ if 'urn:xmpp:attention:0' in features:
+ self.remote_supports_attention = True
+ self.register_command('attention', self.command_attention,
+ usage=_('[message]'),
+ shortdesc=_('Request the attention.'),
+ desc=_('Attention: Request the attention of '
+ 'the contact. Can also send a message'
+ ' along with the attention.'))
+ else:
+ self.remote_supports_attention = False
+
+ def _feature_correct(self, features):
+ "Check for the 'correction' feature"
+ if not 'urn:xmpp:message-correct:0' in features:
+ if 'correct' in self.commands:
+ del self.commands['correct']
+ elif not 'correct' in self.commands:
+ self.register_command('correct', self.command_correct,
+ desc=_('Fix the last message with whatever you want.'),
+ shortdesc=_('Correct the last message.'),
+ completion=self.completion_correct)
+
+ def _feature_receipts(self, features):
+ "Check for the 'receipts' feature"
+ if 'urn:xmpp:receipts' in features:
+ self.remote_supports_receipts = True
+ else:
+ self.remote_supports_receipts = False
+
+ def features_checked(self, iq):
+ "Features check callback"
+ features = iq['disco_info'].get_features() or []
+ log.debug('\n\nFEATURES:\n%s\n\n%s\n\n', iq, features)
+ self._feature_correct(features)
+ self._feature_attention(features)
+ self._feature_receipts(features)
+
+
diff --git a/src/tabs/conversationtab.py b/src/tabs/conversationtab.py
index 7480906b..e6324182 100644
--- a/src/tabs/conversationtab.py
+++ b/src/tabs/conversationtab.py
@@ -18,7 +18,7 @@ log = logging.getLogger(__name__)
import curses
-from . import ChatTab, Tab
+from . basetabs import OneToOneTab, Tab
import common
import fixes
@@ -30,7 +30,7 @@ from decorators import refresh_wrapper
from roster import roster
from theming import get_theme, dump_tuple
-class ConversationTab(ChatTab):
+class ConversationTab(OneToOneTab):
"""
The tab containg a normal conversation (not from a MUC)
Must not be instantiated, use Static or Dynamic version only.
@@ -40,7 +40,7 @@ class ConversationTab(ChatTab):
additional_informations = {}
message_type = 'chat'
def __init__(self, jid):
- ChatTab.__init__(self, jid)
+ OneToOneTab.__init__(self, jid)
self.nick = None
self.nick_sent = False
self.state = 'normal'
@@ -49,7 +49,6 @@ class ConversationTab(ChatTab):
self._text_buffer.add_window(self.text_win)
self.upper_bar = windows.ConversationStatusMessageWin()
self.input = windows.MessageInput()
- self.check_attention()
# keys
self.key_func['^I'] = self.completion
# commands
@@ -142,6 +141,8 @@ class ConversationTab(ChatTab):
typ=1)
self.last_sent_message = msg
+ if self.remote_supports_receipts:
+ msg._add_receipt = True
msg.send()
self.cancel_paused_delay()
self.text_win.refresh()
@@ -208,32 +209,6 @@ class ConversationTab(ChatTab):
self._text_buffer.add_message("\x19%(info_col)s}No information available\x19o" % {'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)})
return True
-
- def command_attention(self, message=''):
- if message is not '':
- self.command_say(message, attention=True)
- else:
- msg = self.core.xmpp.make_message(self.get_dest_jid())
- msg['type'] = 'chat'
- msg['attention'] = True
- msg.send()
-
- def check_attention(self):
- self.core.xmpp.plugin['xep_0030'].get_info(
- jid=self.get_dest_jid(), 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.remote_supports_attention = False
-
def command_unquery(self, arg):
self.core.close_tab()
@@ -416,6 +391,7 @@ class DynamicConversationTab(ConversationTab):
self.name,
resource)
self.add_message(message, typ=0)
+ self.check_features()
def unlock_command(self, arg=None):
self.unlock()
diff --git a/src/tabs/privatetab.py b/src/tabs/privatetab.py
index b8699bd2..6ab06744 100644
--- a/src/tabs/privatetab.py
+++ b/src/tabs/privatetab.py
@@ -17,7 +17,7 @@ log = logging.getLogger(__name__)
import curses
-from . import ChatTab, MucTab, Tab
+from . import OneToOneTab, MucTab, Tab
import fixes
import windows
@@ -28,7 +28,7 @@ from decorators import refresh_wrapper
from logger import logger
from theming import get_theme, dump_tuple
-class PrivateTab(ChatTab):
+class PrivateTab(OneToOneTab):
"""
The tab containg a private conversation (someone from a MUC)
"""
@@ -37,14 +37,13 @@ class PrivateTab(ChatTab):
additional_informations = {}
plugin_keys = {}
def __init__(self, name, nick):
- ChatTab.__init__(self, name)
+ OneToOneTab.__init__(self, name)
self.own_nick = nick
self.name = name
self.text_win = windows.TextWin()
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
@@ -68,6 +67,9 @@ class PrivateTab(ChatTab):
def general_jid(self):
return self.name
+ def get_dest_jid(self):
+ return self.name
+
@property
def nick(self):
return self.get_nick()
@@ -172,36 +174,13 @@ class PrivateTab(ChatTab):
typ=1)
self.last_sent_message = msg
+ if self.remote_supports_receipts:
+ msg._add_receipt = True
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.name)
- msg['type'] = 'chat'
- msg['attention'] = True
- msg.send()
-
- def check_attention(self):
- self.core.xmpp.plugin['xep_0030'].get_info(jid=self.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.remote_supports_attention = False
-
def command_unquery(self, arg):
"""
/unquery