summaryrefslogtreecommitdiff
path: root/src/tabs.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/tabs.py')
-rw-r--r--src/tabs.py54
1 files changed, 53 insertions, 1 deletions
diff --git a/src/tabs.py b/src/tabs.py
index c84ba0fa..ac434745 100644
--- a/src/tabs.py
+++ b/src/tabs.py
@@ -40,6 +40,8 @@ import common
import core
import singleton
import xhtml
+import weakref
+import timed_events
import multiuserchat as muc
@@ -50,6 +52,8 @@ from contact import Contact, Resource
from user import User
from logger import logger
+from datetime import datetime, timedelta
+
SHOW_NAME = {
'dnd': _('busy'),
'away': _('away'),
@@ -245,6 +249,12 @@ class ChatTab(Tab):
# 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
+ self.timed_event_paused = None
+ # 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.key_func['M-/'] = self.last_words_completion
self.key_func['^M'] = self.on_enter
self.commands['say'] = (self.command_say,
@@ -281,6 +291,7 @@ class ChatTab(Tab):
"""
Send an empty chatstate message
"""
+ state = '%s' % state
msg = self.core.xmpp.make_message(self.get_name())
msg['type'] = self.message_type
msg['chat_state'] = state
@@ -294,9 +305,41 @@ class ChatTab(Tab):
if config.get('send_chat_states', 'true') == 'true' and self.remote_wants_chatstates:
if not empty_before and empty_after:
self.send_chat_state("active")
- elif empty_before and not empty_after:
+ elif (empty_before or (self.timed_event_paused is not None and not self.timed_event_paused())) and not empty_after:
self.send_chat_state("composing")
+ def set_paused_delay(self, composing):
+ """
+ we create a timed event that will put us to paused
+ in a few seconds
+ """
+ if config.get('send_chat_states', 'true') != 'true':
+ return
+ if self.timed_event_paused:
+ # check the weakref
+ event = self.timed_event_paused()
+ if event:
+ # the event already exists: we just update
+ # its date
+ event.change_date(datetime.now() + timedelta(seconds=4))
+ return
+ new_event = timed_events.DelayedEvent(4, self.send_chat_state, 'paused')
+ self.core.add_timed_event(new_event)
+ self.timed_event_paused = weakref.ref(new_event)
+
+ def cancel_paused_delay(self):
+ """
+ Remove that event from the list and set it to None.
+ Called for example when the input is emptied, or when the message
+ is sent
+ """
+ if self.timed_event_paused:
+ event = self.timed_event_paused()
+ if event:
+ self.core.timed_events.remove(event)
+ del event
+ self.timed_event_paused = None
+
def command_say(self, line):
raise NotImplementedError
@@ -643,6 +686,9 @@ class MucTab(ChatTab):
self.input.do_command(key)
empty_after = self.input.get_text() == '' or (self.input.get_text().startswith('/') and not self.input.get_text().startswith('//'))
self.send_composing_chat_state(empty_before, empty_after)
+ if not empty_before and empty_after:
+ self.cancel_paused_delay()
+ self.set_paused_delay(empty_before and not empty_after)
return False
def completion(self):
@@ -975,6 +1021,9 @@ class PrivateTab(ChatTab):
self.input.do_command(key)
empty_after = self.input.get_text() == '' or (self.input.get_text().startswith('/') and not self.input.get_text().startswith('//'))
self.send_composing_chat_state(empty_before, empty_after)
+ if not empty_before and empty_after:
+ self.cancel_paused_delay()
+ self.set_paused_delay(empty_before and not empty_after)
return False
def on_lose_focus(self):
@@ -1399,6 +1448,9 @@ class ConversationTab(ChatTab):
self.input.do_command(key)
empty_after = self.input.get_text() == '' or (self.input.get_text().startswith('/') and not self.input.get_text().startswith('//'))
self.send_composing_chat_state(empty_before, empty_after)
+ if not empty_before and empty_after:
+ self.cancel_paused_delay()
+ self.set_paused_delay(empty_before and not empty_after)
return False
def on_lose_focus(self):