Fix a few things regarding chatstates

- Fix wrong chatstates issued because of textview changed signal
- Fix chatstates in PMs
This commit is contained in:
Philipp Hörist 2018-10-09 00:01:35 +02:00
parent e3cf8c00c5
commit 59a5f20ae0
5 changed files with 77 additions and 35 deletions

View File

@ -134,11 +134,6 @@ class ChatControl(ChatControlBase):
self.show_avatar() self.show_avatar()
# Hook up signals # Hook up signals
message_tv_buffer = self.msg_textview.get_buffer()
id_ = message_tv_buffer.connect('changed',
self._on_message_tv_buffer_changed)
self.handlers[id_] = message_tv_buffer
widget = self.xml.get_object('avatar_eventbox') widget = self.xml.get_object('avatar_eventbox')
widget.set_property('height-request', AvatarSize.CHAT) widget.set_property('height-request', AvatarSize.CHAT)
@ -680,7 +675,11 @@ class ChatControl(ChatControlBase):
status_escaped = GLib.markup_escape_text(status_reduced) status_escaped = GLib.markup_escape_text(status_reduced)
st = app.config.get('displayed_chat_state_notifications') st = app.config.get('displayed_chat_state_notifications')
cs = app.contacts.get_combined_chatstate(self.account, self.contact.jid) if self.TYPE_ID == 'pm':
cs = self.gc_contact.chatstate
else:
cs = app.contacts.get_combined_chatstate(
self.account, self.contact.jid)
if cs and st in ('composing_only', 'all'): if cs and st in ('composing_only', 'all'):
if contact.show == 'offline': if contact.show == 'offline':
chatstate = '' chatstate = ''
@ -1152,13 +1151,21 @@ class ChatControl(ChatControlBase):
if event.account != self.account: if event.account != self.account:
return return
if event.jid != self.contact.jid: if self.TYPE_ID == 'pm':
return if event.contact != self.gc_contact:
return
else:
if event.contact.jid != self.contact.jid:
return
self.draw_banner_text() self.draw_banner_text()
# update chatstate in tab for this chat # update chatstate in tab for this chat
chatstate = app.contacts.get_combined_chatstate( if event.contact.is_gc_contact:
self.account, self.contact.jid) chatstate = event.contact.chatstate
else:
chatstate = app.contacts.get_combined_chatstate(
self.account, self.contact.jid)
self.parent_win.redraw_tab(self, chatstate) self.parent_win.redraw_tab(self, chatstate)
def _nec_caps_received(self, obj): def _nec_caps_received(self, obj):
@ -1239,12 +1246,6 @@ class ChatControl(ChatControlBase):
dialogs.TransformChatToMUC(self.account, [c.jid], [dropped_jid]) dialogs.TransformChatToMUC(self.account, [c.jid], [dropped_jid])
def _on_message_tv_buffer_changed(self, textbuffer):
super()._on_message_tv_buffer_changed(textbuffer)
if textbuffer.get_char_count() and self.encryption:
app.plugin_manager.extension_point(
'typing' + self.encryption, self)
def restore_conversation(self): def restore_conversation(self):
jid = self.contact.jid jid = self.contact.jid
# don't restore lines if it's a transport # don't restore lines if it's a transport

View File

@ -341,10 +341,9 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
con = app.connections[self.account] con = app.connections[self.account]
con.get_module('Chatstate').set_active(self.contact.jid) con.get_module('Chatstate').set_active(self.contact.jid)
message_tv_buffer = self.msg_textview.get_buffer() id_ = self.msg_textview.connect('text-changed',
id_ = message_tv_buffer.connect('changed',
self._on_message_tv_buffer_changed) self._on_message_tv_buffer_changed)
self.handlers[id_] = message_tv_buffer self.handlers[id_] = self.msg_textview
if parent_win is not None: if parent_win is not None:
id_ = parent_win.window.connect('motion-notify-event', id_ = parent_win.window.connect('motion-notify-event',
self._on_window_motion_notify) self._on_window_motion_notify)
@ -837,10 +836,14 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
con = app.connections[self.account] con = app.connections[self.account]
con.get_module('Chatstate').set_mouse_activity(self.contact) con.get_module('Chatstate').set_mouse_activity(self.contact)
def _on_message_tv_buffer_changed(self, *args): def _on_message_tv_buffer_changed(self, textview, textbuffer):
if textbuffer.get_char_count() and self.encryption:
app.plugin_manager.extension_point(
'typing' + self.encryption, self)
con = app.connections[self.account] con = app.connections[self.account]
con.get_module('Chatstate').set_keyboard_activity(self.contact) con.get_module('Chatstate').set_keyboard_activity(self.contact)
if not self.msg_textview.has_text(): if not textview.has_text():
con.get_module('Chatstate').set_chatstate(self.contact, con.get_module('Chatstate').set_chatstate(self.contact,
Chatstate.ACTIVE) Chatstate.ACTIVE)
return return

View File

@ -103,13 +103,21 @@ class Chatstate:
# Dont show chatstates from our own resources # Dont show chatstates from our own resources
return return
if event.mtype == 'groupchat':
# Not implemented yet
return
chatstate = parse_chatstate(event.stanza) chatstate = parse_chatstate(event.stanza)
if chatstate is None: if chatstate is None:
return return
contact = app.contacts.get_contact_from_full_jid( if event.muc_pm:
self._account, event.fjid) contact = app.contacts.get_gc_contact(
if contact is None or contact.is_gc_contact: self._account, event.jid, event.resource)
else:
contact = app.contacts.get_contact_from_full_jid(
self._account, event.fjid)
if contact is None:
return return
contact.chatstate = chatstate contact.chatstate = chatstate
@ -117,7 +125,7 @@ class Chatstate:
app.nec.push_outgoing_event( app.nec.push_outgoing_event(
NetworkEvent('chatstate-received', NetworkEvent('chatstate-received',
account=self._account, account=self._account,
jid=event.jid)) contact=contact))
def _check_last_interaction(self) -> GLib.SOURCE_CONTINUE: def _check_last_interaction(self) -> GLib.SOURCE_CONTINUE:
setting = app.config.get('outgoing_chat_state_notifications') setting = app.config.get('outgoing_chat_state_notifications')
@ -129,10 +137,10 @@ class Chatstate:
current_state = self._chatstates.get(jid) current_state = self._chatstates.get(jid)
if current_state is None: if current_state is None:
self._last_mouse_activity.pop(jid, None) self._last_mouse_activity.pop(jid, None)
return GLib.SOURCE_CONTINUE continue
if current_state in (State.GONE, State.INACTIVE): if current_state in (State.GONE, State.INACTIVE):
return GLib.SOURCE_CONTINUE continue
new_chatstate = None new_chatstate = None
if now - time_ > INACTIVE_AFTER: if now - time_ > INACTIVE_AFTER:
@ -147,9 +155,15 @@ class Chatstate:
if self._chatstates.get(jid) != new_chatstate: if self._chatstates.get(jid) != new_chatstate:
contact = app.contacts.get_contact(self._account, jid) contact = app.contacts.get_contact(self._account, jid)
if contact is None: if contact is None:
self._last_mouse_activity.pop(jid, None) room, nick = app.get_room_and_nick_from_fjid(jid)
return GLib.SOURCE_CONTINUE contact = app.contacts.get_gc_contact(
self.set_chatstate(contact, new_chatstate) self._account, room, nick)
if contact is not None:
contact = contact.as_contact()
else:
self._last_mouse_activity.pop(jid, None)
continue
self.set_chatstate(contact, new_chatstate)
return GLib.SOURCE_CONTINUE return GLib.SOURCE_CONTINUE
@ -196,8 +210,9 @@ class Chatstate:
if not contact.is_groupchat(): if not contact.is_groupchat():
# Dont leak presence to contacts # Dont leak presence to contacts
# which are not allowed to see our status # which are not allowed to see our status
if contact and contact.sub in ('to', 'none'): if not contact.is_pm_contact:
return if contact and contact.sub in ('to', 'none'):
return
if contact.show == 'offline': if contact.show == 'offline':
return return

View File

@ -21,6 +21,7 @@ import gc
from gi.repository import Gtk from gi.repository import Gtk
from gi.repository import GLib from gi.repository import GLib
from gi.repository import GObject
from gi.repository import Pango from gi.repository import Pango
from gajim.common import app from gajim.common import app
@ -36,6 +37,10 @@ class MessageTextView(Gtk.TextView):
Class for the message textview (where user writes new messages) for Class for the message textview (where user writes new messages) for
chat/groupchat windows chat/groupchat windows
""" """
__gsignals__ = {
'text-changed': (GObject.SIGNAL_RUN_LAST, None, (Gtk.TextBuffer,))
}
UNDO_LIMIT = 20 UNDO_LIMIT = 20
PLACEHOLDER = _('Write a message…') PLACEHOLDER = _('Write a message…')
@ -60,6 +65,9 @@ class MessageTextView(Gtk.TextView):
self.undo_pressed = False self.undo_pressed = False
buffer_ = self.get_buffer() buffer_ = self.get_buffer()
buffer_.connect('changed', self._on_buffer_changed)
self._last_text = ''
self.begin_tags = {} self.begin_tags = {}
self.end_tags = {} self.end_tags = {}
self.color_tags = [] self.color_tags = []
@ -94,6 +102,16 @@ class MessageTextView(Gtk.TextView):
buffer_.insert_with_tags( buffer_.insert_with_tags(
start, self.PLACEHOLDER, self.placeholder_tag) start, self.PLACEHOLDER, self.placeholder_tag)
def _on_buffer_changed(self, *args):
text = self.get_text()
# Because of inserting and removing PLACEHOLDER text
# the signal becomes unreliable when determining if the user
# typed in new text. So we send our own signal depending on if
# there is real new text that is not the PLACEHOLDER
if text != self._last_text:
self.emit('text-changed', self.get_buffer())
self._last_text = text
def has_text(self): def has_text(self):
buf = self.get_buffer() buf = self.get_buffer()
start, end = buf.get_bounds() start, end = buf.get_bounds()

View File

@ -324,9 +324,14 @@ class GajimRemote(Server):
self.on_message_sent) self.on_message_sent)
def on_chatstate_received(self, obj): def on_chatstate_received(self, obj):
chatstate = app.contacts.get_combined_chatstate( if obj.contact.is_gc_contact:
obj.account, obj.jid) jid = obj.contact.get_full_jid()
self.raise_signal('ChatState', (obj.account, [obj.jid, chatstate])) chatstate = obj.contact.chatstate
else:
jid = obj.contact.jid
chatstate = app.contacts.get_combined_chatstate(
obj.account, obj.contact.jid)
self.raise_signal('ChatState', (obj.account, [jid, chatstate]))
def on_message_sent(self, obj): def on_message_sent(self, obj):
try: try: