Philipp Hörist pushed to branch master at gajim / gajim
Commits:
-
7e007a42
by Philipp Hörist at 2018-10-07T20:35:27Z
-
f5659288
by Philipp Hörist at 2018-10-08T22:01:35Z
6 changed files:
- gajim/chat_control.py
- gajim/chat_control_base.py
- gajim/common/contacts.py
- gajim/common/modules/chatstates.py
- gajim/message_textview.py
- gajim/remote_control.py
Changes:
| ... | ... | @@ -134,11 +134,6 @@ class ChatControl(ChatControlBase): |
| 134 | 134 |
self.show_avatar()
|
| 135 | 135 |
|
| 136 | 136 |
# Hook up signals
|
| 137 |
- message_tv_buffer = self.msg_textview.get_buffer()
|
|
| 138 |
- id_ = message_tv_buffer.connect('changed',
|
|
| 139 |
- self._on_message_tv_buffer_changed)
|
|
| 140 |
- self.handlers[id_] = message_tv_buffer
|
|
| 141 |
- |
|
| 142 | 137 |
widget = self.xml.get_object('avatar_eventbox')
|
| 143 | 138 |
widget.set_property('height-request', AvatarSize.CHAT)
|
| 144 | 139 |
|
| ... | ... | @@ -680,7 +675,11 @@ class ChatControl(ChatControlBase): |
| 680 | 675 |
status_escaped = GLib.markup_escape_text(status_reduced)
|
| 681 | 676 |
|
| 682 | 677 |
st = app.config.get('displayed_chat_state_notifications')
|
| 683 |
- cs = app.contacts.get_combined_chatstate(self.account, self.contact.jid)
|
|
| 678 |
+ if self.TYPE_ID == 'pm':
|
|
| 679 |
+ cs = self.gc_contact.chatstate
|
|
| 680 |
+ else:
|
|
| 681 |
+ cs = app.contacts.get_combined_chatstate(
|
|
| 682 |
+ self.account, self.contact.jid)
|
|
| 684 | 683 |
if cs and st in ('composing_only', 'all'):
|
| 685 | 684 |
if contact.show == 'offline':
|
| 686 | 685 |
chatstate = ''
|
| ... | ... | @@ -1152,13 +1151,21 @@ class ChatControl(ChatControlBase): |
| 1152 | 1151 |
if event.account != self.account:
|
| 1153 | 1152 |
return
|
| 1154 | 1153 |
|
| 1155 |
- if event.jid != self.contact.jid:
|
|
| 1156 |
- return
|
|
| 1154 |
+ if self.TYPE_ID == 'pm':
|
|
| 1155 |
+ if event.contact != self.gc_contact:
|
|
| 1156 |
+ return
|
|
| 1157 |
+ else:
|
|
| 1158 |
+ if event.contact.jid != self.contact.jid:
|
|
| 1159 |
+ return
|
|
| 1157 | 1160 |
|
| 1158 | 1161 |
self.draw_banner_text()
|
| 1162 |
+ |
|
| 1159 | 1163 |
# update chatstate in tab for this chat
|
| 1160 |
- chatstate = app.contacts.get_combined_chatstate(
|
|
| 1161 |
- self.account, self.contact.jid)
|
|
| 1164 |
+ if event.contact.is_gc_contact:
|
|
| 1165 |
+ chatstate = event.contact.chatstate
|
|
| 1166 |
+ else:
|
|
| 1167 |
+ chatstate = app.contacts.get_combined_chatstate(
|
|
| 1168 |
+ self.account, self.contact.jid)
|
|
| 1162 | 1169 |
self.parent_win.redraw_tab(self, chatstate)
|
| 1163 | 1170 |
|
| 1164 | 1171 |
def _nec_caps_received(self, obj):
|
| ... | ... | @@ -1239,12 +1246,6 @@ class ChatControl(ChatControlBase): |
| 1239 | 1246 |
|
| 1240 | 1247 |
dialogs.TransformChatToMUC(self.account, [c.jid], [dropped_jid])
|
| 1241 | 1248 |
|
| 1242 |
- def _on_message_tv_buffer_changed(self, textbuffer):
|
|
| 1243 |
- super()._on_message_tv_buffer_changed(textbuffer)
|
|
| 1244 |
- if textbuffer.get_char_count() and self.encryption:
|
|
| 1245 |
- app.plugin_manager.extension_point(
|
|
| 1246 |
- 'typing' + self.encryption, self)
|
|
| 1247 |
- |
|
| 1248 | 1249 |
def restore_conversation(self):
|
| 1249 | 1250 |
jid = self.contact.jid
|
| 1250 | 1251 |
# don't restore lines if it's a transport
|
| ... | ... | @@ -341,10 +341,9 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): |
| 341 | 341 |
con = app.connections[self.account]
|
| 342 | 342 |
con.get_module('Chatstate').set_active(self.contact.jid)
|
| 343 | 343 |
|
| 344 |
- message_tv_buffer = self.msg_textview.get_buffer()
|
|
| 345 |
- id_ = message_tv_buffer.connect('changed',
|
|
| 344 |
+ id_ = self.msg_textview.connect('text-changed',
|
|
| 346 | 345 |
self._on_message_tv_buffer_changed)
|
| 347 |
- self.handlers[id_] = message_tv_buffer
|
|
| 346 |
+ self.handlers[id_] = self.msg_textview
|
|
| 348 | 347 |
if parent_win is not None:
|
| 349 | 348 |
id_ = parent_win.window.connect('motion-notify-event',
|
| 350 | 349 |
self._on_window_motion_notify)
|
| ... | ... | @@ -837,10 +836,14 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): |
| 837 | 836 |
con = app.connections[self.account]
|
| 838 | 837 |
con.get_module('Chatstate').set_mouse_activity(self.contact)
|
| 839 | 838 |
|
| 840 |
- def _on_message_tv_buffer_changed(self, *args):
|
|
| 839 |
+ def _on_message_tv_buffer_changed(self, textview, textbuffer):
|
|
| 840 |
+ if textbuffer.get_char_count() and self.encryption:
|
|
| 841 |
+ app.plugin_manager.extension_point(
|
|
| 842 |
+ 'typing' + self.encryption, self)
|
|
| 843 |
+ |
|
| 841 | 844 |
con = app.connections[self.account]
|
| 842 | 845 |
con.get_module('Chatstate').set_keyboard_activity(self.contact)
|
| 843 |
- if not self.msg_textview.has_text():
|
|
| 846 |
+ if not textview.has_text():
|
|
| 844 | 847 |
con.get_module('Chatstate').set_chatstate(self.contact,
|
| 845 | 848 |
Chatstate.ACTIVE)
|
| 846 | 849 |
return
|
| ... | ... | @@ -60,6 +60,8 @@ class CommonContact(XMPPEntity): |
| 60 | 60 |
# this is contact's chatstate
|
| 61 | 61 |
self._chatstate = chatstate
|
| 62 | 62 |
|
| 63 |
+ self._is_pm_contact = False
|
|
| 64 |
+ |
|
| 63 | 65 |
@property
|
| 64 | 66 |
def show(self):
|
| 65 | 67 |
return self._show
|
| ... | ... | @@ -91,6 +93,10 @@ class CommonContact(XMPPEntity): |
| 91 | 93 |
def is_gc_contact(self):
|
| 92 | 94 |
return isinstance(self, GC_Contact)
|
| 93 | 95 |
|
| 96 |
+ @property
|
|
| 97 |
+ def is_pm_contact(self):
|
|
| 98 |
+ return self._is_pm_contact
|
|
| 99 |
+ |
|
| 94 | 100 |
def get_full_jid(self):
|
| 95 | 101 |
raise NotImplementedError
|
| 96 | 102 |
|
| ... | ... | @@ -117,7 +123,8 @@ class Contact(CommonContact): |
| 117 | 123 |
"""
|
| 118 | 124 |
def __init__(self, jid, account, name='', groups=None, show='', status='',
|
| 119 | 125 |
sub='', ask='', resource='', priority=0, keyID='', client_caps=None,
|
| 120 |
- chatstate=None, idle_time=None, avatar_sha=None, groupchat=False):
|
|
| 126 |
+ chatstate=None, idle_time=None, avatar_sha=None, groupchat=False,
|
|
| 127 |
+ is_pm_contact=False):
|
|
| 121 | 128 |
if not isinstance(jid, str):
|
| 122 | 129 |
print('no str')
|
| 123 | 130 |
if groups is None:
|
| ... | ... | @@ -130,6 +137,7 @@ class Contact(CommonContact): |
| 130 | 137 |
self.groups = [i if i else _('General') for i in set(groups)] # filter duplicate values
|
| 131 | 138 |
self.avatar_sha = avatar_sha
|
| 132 | 139 |
self._is_groupchat = groupchat
|
| 140 |
+ self._is_pm_contact = is_pm_contact
|
|
| 133 | 141 |
|
| 134 | 142 |
self.sub = sub
|
| 135 | 143 |
self.ask = ask
|
| ... | ... | @@ -227,7 +235,8 @@ class GC_Contact(CommonContact): |
| 227 | 235 |
"""
|
| 228 | 236 |
return Contact(jid=self.get_full_jid(), account=self.account,
|
| 229 | 237 |
name=self.name, groups=[], show=self.show, status=self.status,
|
| 230 |
- sub='none', client_caps=self.client_caps, avatar_sha=self.avatar_sha)
|
|
| 238 |
+ sub='none', client_caps=self.client_caps, avatar_sha=self.avatar_sha,
|
|
| 239 |
+ is_pm_contact=True)
|
|
| 231 | 240 |
|
| 232 | 241 |
|
| 233 | 242 |
class LegacyContactsAPI:
|
| ... | ... | @@ -103,13 +103,21 @@ class Chatstate: |
| 103 | 103 |
# Dont show chatstates from our own resources
|
| 104 | 104 |
return
|
| 105 | 105 |
|
| 106 |
+ if event.mtype == 'groupchat':
|
|
| 107 |
+ # Not implemented yet
|
|
| 108 |
+ return
|
|
| 109 |
+ |
|
| 106 | 110 |
chatstate = parse_chatstate(event.stanza)
|
| 107 | 111 |
if chatstate is None:
|
| 108 | 112 |
return
|
| 109 | 113 |
|
| 110 |
- contact = app.contacts.get_contact_from_full_jid(
|
|
| 111 |
- self._account, event.fjid)
|
|
| 112 |
- if contact is None or contact.is_gc_contact:
|
|
| 114 |
+ if event.muc_pm:
|
|
| 115 |
+ contact = app.contacts.get_gc_contact(
|
|
| 116 |
+ self._account, event.jid, event.resource)
|
|
| 117 |
+ else:
|
|
| 118 |
+ contact = app.contacts.get_contact_from_full_jid(
|
|
| 119 |
+ self._account, event.fjid)
|
|
| 120 |
+ if contact is None:
|
|
| 113 | 121 |
return
|
| 114 | 122 |
|
| 115 | 123 |
contact.chatstate = chatstate
|
| ... | ... | @@ -117,7 +125,7 @@ class Chatstate: |
| 117 | 125 |
app.nec.push_outgoing_event(
|
| 118 | 126 |
NetworkEvent('chatstate-received',
|
| 119 | 127 |
account=self._account,
|
| 120 |
- jid=event.jid))
|
|
| 128 |
+ contact=contact))
|
|
| 121 | 129 |
|
| 122 | 130 |
def _check_last_interaction(self) -> GLib.SOURCE_CONTINUE:
|
| 123 | 131 |
setting = app.config.get('outgoing_chat_state_notifications')
|
| ... | ... | @@ -129,10 +137,10 @@ class Chatstate: |
| 129 | 137 |
current_state = self._chatstates.get(jid)
|
| 130 | 138 |
if current_state is None:
|
| 131 | 139 |
self._last_mouse_activity.pop(jid, None)
|
| 132 |
- return GLib.SOURCE_CONTINUE
|
|
| 140 |
+ continue
|
|
| 133 | 141 |
|
| 134 | 142 |
if current_state in (State.GONE, State.INACTIVE):
|
| 135 |
- return GLib.SOURCE_CONTINUE
|
|
| 143 |
+ continue
|
|
| 136 | 144 |
|
| 137 | 145 |
new_chatstate = None
|
| 138 | 146 |
if now - time_ > INACTIVE_AFTER:
|
| ... | ... | @@ -147,9 +155,15 @@ class Chatstate: |
| 147 | 155 |
if self._chatstates.get(jid) != new_chatstate:
|
| 148 | 156 |
contact = app.contacts.get_contact(self._account, jid)
|
| 149 | 157 |
if contact is None:
|
| 150 |
- self._last_mouse_activity.pop(jid, None)
|
|
| 151 |
- return GLib.SOURCE_CONTINUE
|
|
| 152 |
- self.set_chatstate(contact, new_chatstate)
|
|
| 158 |
+ room, nick = app.get_room_and_nick_from_fjid(jid)
|
|
| 159 |
+ contact = app.contacts.get_gc_contact(
|
|
| 160 |
+ self._account, room, nick)
|
|
| 161 |
+ if contact is not None:
|
|
| 162 |
+ contact = contact.as_contact()
|
|
| 163 |
+ else:
|
|
| 164 |
+ self._last_mouse_activity.pop(jid, None)
|
|
| 165 |
+ continue
|
|
| 166 |
+ self.set_chatstate(contact, new_chatstate)
|
|
| 153 | 167 |
|
| 154 | 168 |
return GLib.SOURCE_CONTINUE
|
| 155 | 169 |
|
| ... | ... | @@ -196,8 +210,9 @@ class Chatstate: |
| 196 | 210 |
if not contact.is_groupchat():
|
| 197 | 211 |
# Dont leak presence to contacts
|
| 198 | 212 |
# which are not allowed to see our status
|
| 199 |
- if contact and contact.sub in ('to', 'none'):
|
|
| 200 |
- return
|
|
| 213 |
+ if not contact.is_pm_contact:
|
|
| 214 |
+ if contact and contact.sub in ('to', 'none'):
|
|
| 215 |
+ return
|
|
| 201 | 216 |
|
| 202 | 217 |
if contact.show == 'offline':
|
| 203 | 218 |
return
|
| ... | ... | @@ -21,6 +21,7 @@ import gc |
| 21 | 21 |
|
| 22 | 22 |
from gi.repository import Gtk
|
| 23 | 23 |
from gi.repository import GLib
|
| 24 |
+from gi.repository import GObject
|
|
| 24 | 25 |
from gi.repository import Pango
|
| 25 | 26 |
|
| 26 | 27 |
from gajim.common import app
|
| ... | ... | @@ -36,6 +37,10 @@ class MessageTextView(Gtk.TextView): |
| 36 | 37 |
Class for the message textview (where user writes new messages) for
|
| 37 | 38 |
chat/groupchat windows
|
| 38 | 39 |
"""
|
| 40 |
+ __gsignals__ = {
|
|
| 41 |
+ 'text-changed': (GObject.SIGNAL_RUN_LAST, None, (Gtk.TextBuffer,))
|
|
| 42 |
+ }
|
|
| 43 |
+ |
|
| 39 | 44 |
UNDO_LIMIT = 20
|
| 40 | 45 |
PLACEHOLDER = _('Write a message…')
|
| 41 | 46 |
|
| ... | ... | @@ -60,6 +65,9 @@ class MessageTextView(Gtk.TextView): |
| 60 | 65 |
self.undo_pressed = False
|
| 61 | 66 |
|
| 62 | 67 |
buffer_ = self.get_buffer()
|
| 68 |
+ buffer_.connect('changed', self._on_buffer_changed)
|
|
| 69 |
+ self._last_text = ''
|
|
| 70 |
+ |
|
| 63 | 71 |
self.begin_tags = {}
|
| 64 | 72 |
self.end_tags = {}
|
| 65 | 73 |
self.color_tags = []
|
| ... | ... | @@ -94,6 +102,16 @@ class MessageTextView(Gtk.TextView): |
| 94 | 102 |
buffer_.insert_with_tags(
|
| 95 | 103 |
start, self.PLACEHOLDER, self.placeholder_tag)
|
| 96 | 104 |
|
| 105 |
+ def _on_buffer_changed(self, *args):
|
|
| 106 |
+ text = self.get_text()
|
|
| 107 |
+ # Because of inserting and removing PLACEHOLDER text
|
|
| 108 |
+ # the signal becomes unreliable when determining if the user
|
|
| 109 |
+ # typed in new text. So we send our own signal depending on if
|
|
| 110 |
+ # there is real new text that is not the PLACEHOLDER
|
|
| 111 |
+ if text != self._last_text:
|
|
| 112 |
+ self.emit('text-changed', self.get_buffer())
|
|
| 113 |
+ self._last_text = text
|
|
| 114 |
+ |
|
| 97 | 115 |
def has_text(self):
|
| 98 | 116 |
buf = self.get_buffer()
|
| 99 | 117 |
start, end = buf.get_bounds()
|
| ... | ... | @@ -324,9 +324,14 @@ class GajimRemote(Server): |
| 324 | 324 |
self.on_message_sent)
|
| 325 | 325 |
|
| 326 | 326 |
def on_chatstate_received(self, obj):
|
| 327 |
- chatstate = app.contacts.get_combined_chatstate(
|
|
| 328 |
- obj.account, obj.jid)
|
|
| 329 |
- self.raise_signal('ChatState', (obj.account, [obj.jid, chatstate]))
|
|
| 327 |
+ if obj.contact.is_gc_contact:
|
|
| 328 |
+ jid = obj.contact.get_full_jid()
|
|
| 329 |
+ chatstate = obj.contact.chatstate
|
|
| 330 |
+ else:
|
|
| 331 |
+ jid = obj.contact.jid
|
|
| 332 |
+ chatstate = app.contacts.get_combined_chatstate(
|
|
| 333 |
+ obj.account, obj.contact.jid)
|
|
| 334 |
+ self.raise_signal('ChatState', (obj.account, [jid, chatstate]))
|
|
| 330 | 335 |
|
| 331 | 336 |
def on_message_sent(self, obj):
|
| 332 | 337 |
try:
|