In normal conversations: Send composing and active chat states
and display the state of the remote contact
This commit is contained in:
parent
cc74576c9f
commit
138b17cdb3
4 changed files with 90 additions and 12 deletions
|
@ -55,6 +55,7 @@ class Connection(sleekxmpp.ClientXMPP):
|
|||
self.register_plugin('xep_0030')
|
||||
self.register_plugin('xep_0045')
|
||||
self.register_plugin('xep_0004')
|
||||
self.register_plugin('xep_0085')
|
||||
if config.get('send_poezio_info', 'true') == 'true':
|
||||
info = {'name':'poezio',
|
||||
'version':'0.7.5-dev'}
|
||||
|
|
65
src/core.py
65
src/core.py
|
@ -170,7 +170,11 @@ class Core(object):
|
|||
self.xmpp.add_event_handler("changed_status", self.on_presence)
|
||||
self.xmpp.add_event_handler("changed_subscription", self.on_changed_subscription)
|
||||
self.xmpp.add_event_handler("message_xform", self.on_data_form)
|
||||
|
||||
self.xmpp.add_event_handler("chatstate_active", self.on_chatstate_active)
|
||||
self.xmpp.add_event_handler("chatstate_composing", self.on_chatstate_composing)
|
||||
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.information(_('Welcome to poezio!'))
|
||||
self.refresh_window()
|
||||
|
||||
|
@ -214,6 +218,32 @@ class Core(object):
|
|||
"""
|
||||
self.information('%s' % messsage)
|
||||
|
||||
def on_chatstate_active(self, message):
|
||||
if message['type'] == 'chat': # normal conversation
|
||||
self.on_chatstate_normal_conversation("active")
|
||||
|
||||
def on_chatstate_inactive(self, message):
|
||||
if message['type'] == 'chat': # normal conversation
|
||||
self.on_chatstate_normal_conversation("inactive")
|
||||
|
||||
def on_chatstate_composing(self, message):
|
||||
if message['type'] == 'chat':
|
||||
self.on_chatstate_normal_conversation("composing")
|
||||
|
||||
def on_chatstate_paused(self, message):
|
||||
if message['type'] == 'chat':
|
||||
self.on_chatstate_normal_conversation("paused")
|
||||
|
||||
def on_chatstate_gone(self, message):
|
||||
if message['type'] == 'chat':
|
||||
self.on_chatstate_normal_conversation("gone")
|
||||
|
||||
def on_chatstate_normal_conversation(self, state):
|
||||
tab = self.get_tab_of_conversation_with_jid(message['from'], False)
|
||||
if not tab:
|
||||
return
|
||||
tab.chatstate = state
|
||||
|
||||
def open_new_form(self, form, on_cancel, on_send, **kwargs):
|
||||
"""
|
||||
Open a new tab containing the form
|
||||
|
@ -577,6 +607,25 @@ class Core(object):
|
|||
if tab.get_name() == tab_name:
|
||||
self.command_win('%s' % (tab.nb,))
|
||||
|
||||
def get_tab_of_conversation_with_jid(self, jid, create=True):
|
||||
"""
|
||||
From a JID, get the tab containing the conversation with it.
|
||||
If none already exist, and create is "True", we create it
|
||||
and return it. Otherwise, we return None
|
||||
"""
|
||||
# We first check if we have a conversation opened with this precise resource
|
||||
conversation = self.get_tab_by_name(jid.full, tabs.ConversationTab)
|
||||
if not conversation:
|
||||
# If not, we search for a conversation with the bare jid
|
||||
conversation = self.get_tab_by_name(jid.bare, tabs.ConversationTab)
|
||||
if not conversation:
|
||||
if create:
|
||||
# We create the conversation with the bare Jid if nothing was found
|
||||
conversation = self.open_conversation_window(jid.bare, False)
|
||||
else:
|
||||
conversation = None
|
||||
return conversation
|
||||
|
||||
def on_normal_message(self, message):
|
||||
"""
|
||||
When receiving "normal" messages (from someone in our roster)
|
||||
|
@ -585,19 +634,17 @@ class Core(object):
|
|||
body = message['body']
|
||||
if not body:
|
||||
return
|
||||
# We first check if we have a conversation opened with this precise resource
|
||||
conversation = self.get_tab_by_name(jid.full, tabs.ConversationTab)
|
||||
if not conversation:
|
||||
# If not, we search for a conversation with the bare jid
|
||||
conversation = self.get_tab_by_name(jid.bare, tabs.ConversationTab)
|
||||
if not conversation:
|
||||
# We create the conversation with the bare Jid if nothing was found
|
||||
conversation = self.open_conversation_window(jid.bare, False)
|
||||
conversation = self.get_tab_of_conversation_with_jid(jid, create=True)
|
||||
if roster.get_contact_by_jid(jid.bare):
|
||||
remote_nick = roster.get_contact_by_jid(jid.bare).get_name() or jid.user
|
||||
else:
|
||||
remote_nick = jid.user
|
||||
conversation.get_room().add_message(body, None, remote_nick, False, theme.COLOR_REMOTE_USER)
|
||||
if conversation.remote_wants_chatstates is None:
|
||||
if message['chat_state']:
|
||||
conversation.remote_wants_chatstates = True
|
||||
else:
|
||||
conversation.remote_wants_chatstates = False
|
||||
logger.log_message(jid.bare, remote_nick, body)
|
||||
if self.current_tab() is not conversation:
|
||||
conversation.set_color_state(theme.COLOR_TAB_PRIVATE)
|
||||
|
|
29
src/tabs.py
29
src/tabs.py
|
@ -225,6 +225,10 @@ class ChatTab(Tab):
|
|||
def __init__(self, core, room):
|
||||
Tab.__init__(self, core)
|
||||
self._room = room
|
||||
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"
|
||||
self.key_func['M-/'] = self.last_words_completion
|
||||
self.key_func['^M'] = self.on_enter
|
||||
self.commands['say'] = (self.command_say,
|
||||
|
@ -355,6 +359,10 @@ class MucTab(ChatTab, TabWithInfoWin):
|
|||
def __init__(self, core, room):
|
||||
ChatTab.__init__(self, core, room)
|
||||
TabWithInfoWin.__init__(self)
|
||||
self.remote_wants_chatstates = True
|
||||
# We send active, composing and paused states to the MUC because
|
||||
# the chatstate may or may not be filtered by the MUC,
|
||||
# that’s not our problem.
|
||||
self.topic_win = windows.Topic()
|
||||
self.text_win = windows.TextWin()
|
||||
room.add_window(self.text_win)
|
||||
|
@ -1103,7 +1111,12 @@ class ConversationTab(ChatTab, TabWithInfoWin):
|
|||
self.complete_commands(self.input)
|
||||
|
||||
def command_say(self, line):
|
||||
muc.send_private_message(self.core.xmpp, self.get_name(), line)
|
||||
msg = self.core.xmpp.make_message(self.get_name())
|
||||
msg['type'] = 'chat'
|
||||
msg['body'] = line
|
||||
if self.remote_wants_chatstates is not False:
|
||||
msg['chat_state'] = 'active'
|
||||
msg.send()
|
||||
self.core.add_message_to_text_buffer(self.get_room(), line, None, self.core.own_nick)
|
||||
logger.log_message(JID(self.get_name()).bare, self.core.own_nick, line)
|
||||
|
||||
|
@ -1131,7 +1144,7 @@ class ConversationTab(ChatTab, TabWithInfoWin):
|
|||
self.resize()
|
||||
self.text_win.refresh(self._room)
|
||||
self.upper_bar.refresh(self.get_name(), roster.get_contact_by_jid(self.get_name()))
|
||||
self.info_header.refresh(self.get_name(), roster.get_contact_by_jid(self.get_name()), self._room, self.text_win)
|
||||
self.info_header.refresh(self.get_name(), roster.get_contact_by_jid(self.get_name()), self._room, self.text_win, self.chatstate)
|
||||
self.info_win.refresh(informations)
|
||||
self.tab_win.refresh(tabs, tabs[0])
|
||||
self.input.refresh()
|
||||
|
@ -1152,7 +1165,19 @@ class ConversationTab(ChatTab, TabWithInfoWin):
|
|||
if key in self.key_func:
|
||||
self.key_func[key]()
|
||||
return False
|
||||
empty_before = self.input.get_text() == ''
|
||||
self.input.do_command(key)
|
||||
if not self.input.get_text() and not empty_before:
|
||||
msg = self.core.xmpp.make_message(self.get_name())
|
||||
msg['type'] = 'chat'
|
||||
msg['chat_state'] = 'active'
|
||||
msg.send()
|
||||
elif self.input.get_text() and empty_before:
|
||||
msg = self.core.xmpp.make_message(self.get_name())
|
||||
msg['type'] = 'chat'
|
||||
msg['chat_state'] = 'composing'
|
||||
log.debug('MSG:%s\n' % msg)
|
||||
msg.send()
|
||||
return False
|
||||
|
||||
def on_lose_focus(self):
|
||||
|
|
|
@ -282,7 +282,7 @@ class ConversationInfoWin(InfoWin):
|
|||
def resize(self, height, width, y, x, stdscr):
|
||||
self._resize(height, width, y, x, stdscr)
|
||||
|
||||
def refresh(self, jid, contact, text_buffer, window):
|
||||
def refresh(self, jid, contact, text_buffer, window, chatstate):
|
||||
# contact can be None, if we receive a message
|
||||
# from someone not in our roster. In this case, we display
|
||||
# only the maximum information from the message we can get.
|
||||
|
@ -305,6 +305,7 @@ class ConversationInfoWin(InfoWin):
|
|||
self.write_contact_informations(contact)
|
||||
self.write_resource_information(resource)
|
||||
self.print_scroll_position(window)
|
||||
self.write_chatstate(chatstate)
|
||||
self.finish_line(theme.COLOR_INFORMATION_BAR)
|
||||
self._refresh()
|
||||
|
||||
|
@ -339,6 +340,10 @@ class ConversationInfoWin(InfoWin):
|
|||
self.addstr(jid.full, common.curses_color_pair(theme.COLOR_CONVERSATION_NAME))
|
||||
self.addstr('] ', common.curses_color_pair(theme.COLOR_INFORMATION_BAR))
|
||||
|
||||
def write_chatstate(self, state):
|
||||
if state:
|
||||
self.addstr(' %s' % (state,), common.curses_color_pair(theme.COLOR_INFORMATION_BAR))
|
||||
|
||||
class ConversationStatusMessageWin(InfoWin):
|
||||
"""
|
||||
The upper bar displaying the status message of the contact
|
||||
|
|
Loading…
Reference in a new issue