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()
# 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.set_property('height-request', AvatarSize.CHAT)
@ -680,7 +675,11 @@ class ChatControl(ChatControlBase):
status_escaped = GLib.markup_escape_text(status_reduced)
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 contact.show == 'offline':
chatstate = ''
@ -1152,11 +1151,19 @@ class ChatControl(ChatControlBase):
if event.account != self.account:
return
if event.jid != self.contact.jid:
if self.TYPE_ID == 'pm':
if event.contact != self.gc_contact:
return
else:
if event.contact.jid != self.contact.jid:
return
self.draw_banner_text()
# update chatstate in tab for this chat
if event.contact.is_gc_contact:
chatstate = event.contact.chatstate
else:
chatstate = app.contacts.get_combined_chatstate(
self.account, self.contact.jid)
self.parent_win.redraw_tab(self, chatstate)
@ -1239,12 +1246,6 @@ class ChatControl(ChatControlBase):
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):
jid = self.contact.jid
# 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.get_module('Chatstate').set_active(self.contact.jid)
message_tv_buffer = self.msg_textview.get_buffer()
id_ = message_tv_buffer.connect('changed',
id_ = self.msg_textview.connect('text-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:
id_ = parent_win.window.connect('motion-notify-event',
self._on_window_motion_notify)
@ -837,10 +836,14 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
con = app.connections[self.account]
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.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,
Chatstate.ACTIVE)
return

View File

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

View File

@ -21,6 +21,7 @@ import gc
from gi.repository import Gtk
from gi.repository import GLib
from gi.repository import GObject
from gi.repository import Pango
from gajim.common import app
@ -36,6 +37,10 @@ class MessageTextView(Gtk.TextView):
Class for the message textview (where user writes new messages) for
chat/groupchat windows
"""
__gsignals__ = {
'text-changed': (GObject.SIGNAL_RUN_LAST, None, (Gtk.TextBuffer,))
}
UNDO_LIMIT = 20
PLACEHOLDER = _('Write a message…')
@ -60,6 +65,9 @@ class MessageTextView(Gtk.TextView):
self.undo_pressed = False
buffer_ = self.get_buffer()
buffer_.connect('changed', self._on_buffer_changed)
self._last_text = ''
self.begin_tags = {}
self.end_tags = {}
self.color_tags = []
@ -94,6 +102,16 @@ class MessageTextView(Gtk.TextView):
buffer_.insert_with_tags(
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):
buf = self.get_buffer()
start, end = buf.get_bounds()

View File

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