Commit f0a4094c authored by Yann Leboulanger's avatar Yann Leboulanger

XEP-0308 Last Message Correction support.

parent c6c3f263
This diff is collapsed.
......@@ -254,9 +254,11 @@ class CommonConnection:
def _prepare_message(self, jid, msg, keyID, type_='chat', subject='',
chatstate=None, msg_id=None, resource=None, user_nick=None, xhtml=None,
session=None, forward_from=None, form_node=None, label=None,
original_message=None, delayed=None, attention=False, callback=None):
original_message=None, delayed=None, attention=False, correction_msg=None,
callback=None):
if not self.connection or self.connected < 2:
return 1
try:
jid = self.check_jid(jid)
except helpers.InvalidFormat:
......@@ -306,7 +308,7 @@ class CommonConnection:
jid, xhtml, subject, chatstate, msg_id,
label, forward_from, delayed, session,
form_node, user_nick, keyID, attention,
callback)
correction_msg, callback)
gajim.nec.push_incoming_event(GPGTrustKeyEvent(None,
conn=self, callback=_on_always_trust))
else:
......@@ -314,7 +316,7 @@ class CommonConnection:
original_message, fjid, resource, jid, xhtml,
subject, chatstate, msg_id, label, forward_from,
delayed, session, form_node, user_nick, keyID,
attention, callback)
attention, correction_msg, callback)
gajim.thread_interface(encrypt_thread, [msg, keyID, False],
_on_encrypted, [])
return
......@@ -322,18 +324,19 @@ class CommonConnection:
self._message_encrypted_cb(('', error), type_, msg, msgtxt,
original_message, fjid, resource, jid, xhtml, subject,
chatstate, msg_id, label, forward_from, delayed, session,
form_node, user_nick, keyID, attention, callback)
form_node, user_nick, keyID, attention, correction_msg,
callback)
return
self._on_continue_message(type_, msg, msgtxt, original_message, fjid,
resource, jid, xhtml, subject, msgenc, keyID, chatstate, msg_id,
label, forward_from, delayed, session, form_node, user_nick,
attention, callback)
attention, correction_msg, callback)
def _message_encrypted_cb(self, output, type_, msg, msgtxt,
original_message, fjid, resource, jid, xhtml, subject, chatstate, msg_id,
label, forward_from, delayed, session, form_node, user_nick, keyID,
attention, callback):
attention, correction_msg, callback):
msgenc, error = output
if msgenc and not error:
......@@ -346,7 +349,7 @@ class CommonConnection:
self._on_continue_message(type_, msg, msgtxt, original_message,
fjid, resource, jid, xhtml, subject, msgenc, keyID,
chatstate, msg_id, label, forward_from, delayed, session,
form_node, user_nick, attention, callback)
form_node, user_nick, attention, correction_msg, callback)
return
# Encryption failed, do not send message
tim = localtime()
......@@ -356,7 +359,32 @@ class CommonConnection:
def _on_continue_message(self, type_, msg, msgtxt, original_message, fjid,
resource, jid, xhtml, subject, msgenc, keyID, chatstate, msg_id,
label, forward_from, delayed, session, form_node, user_nick, attention,
callback):
correction_msg, callback):
if correction_msg:
id_ = correction_msg.getID()
if correction_msg.getTag('replace'):
correction_msg.delChild('replace')
correction_msg.setTag('replace', attrs={'id': id_},
namespace=nbxmpp.NS_CORRECT)
id2 = self.connection.getAnID()
correction_msg.setID(id2)
correction_msg.setBody(msgtxt)
if xhtml:
correction_msg.setXHTML(xhtml)
if session:
session.last_send = time.time()
# XEP-0200
if session.enable_encryption:
correction_msg = session.encrypt_stanza(correction_msg)
if callback:
callback(jid, msg, keyID, forward_from, session, original_message,
subject, type_, correction_msg, xhtml)
return
if type_ == 'chat':
msg_iq = nbxmpp.Message(to=fjid, body=msgtxt, typ=type_,
xhtml=xhtml)
......@@ -1941,8 +1969,8 @@ class Connection(CommonConnection, ConnectionHandlers):
def send_message(self, jid, msg, keyID=None, type_='chat', subject='',
chatstate=None, msg_id=None, resource=None, user_nick=None, xhtml=None,
label=None, session=None, forward_from=None, form_node=None,
original_message=None, delayed=None, attention=False, callback=None,
callback_args=[], now=False):
original_message=None, delayed=None, attention=False, correction_msg=None,
callback=None, callback_args=[], now=False):
def cb(jid, msg, keyID, forward_from, session, original_message,
subject, type_, msg_iq, xhtml):
......@@ -1961,7 +1989,7 @@ class Connection(CommonConnection, ConnectionHandlers):
user_nick=user_nick, xhtml=xhtml, label=label, session=session,
forward_from=forward_from, form_node=form_node,
original_message=original_message, delayed=delayed,
attention=attention, callback=cb)
attention=attention, correction_msg=correction_msg, callback=cb)
def _nec_message_outgoing(self, obj):
if obj.account != self.name:
......@@ -1974,7 +2002,7 @@ class Connection(CommonConnection, ConnectionHandlers):
gajim.nec.push_incoming_event(MessageSentEvent(None, conn=self,
jid=jid, message=msg, keyID=keyID, chatstate=obj.chatstate))
if obj.callback:
obj.callback(msg_id, *obj.callback_args)
obj.callback(msg_iq, *obj.callback_args)
if not obj.is_loggable:
return
......@@ -1986,7 +2014,8 @@ class Connection(CommonConnection, ConnectionHandlers):
resource=obj.resource, user_nick=obj.user_nick, xhtml=obj.xhtml,
label=obj.label, session=obj.session, forward_from=obj.forward_from,
form_node=obj.form_node, original_message=obj.original_message,
delayed=obj.delayed, attention=obj.attention, callback=cb)
delayed=obj.delayed, attention=obj.attention,
correction_msg=obj.correction_msg, callback=cb)
def send_contacts(self, contacts, fjid, type_='message'):
"""
......@@ -2524,18 +2553,38 @@ class Connection(CommonConnection, ConnectionHandlers):
t.setTagData('password', password)
self.connection.send(p)
def send_gc_message(self, jid, msg, xhtml=None, label=None):
def send_gc_message(self, jid, msg, xhtml=None, label=None,
correction_msg=None, callback=None):
if not gajim.account_is_connected(self.name):
return
if correction_msg:
id_ = correction_msg.getID()
if correction_msg.getTag('replace'):
correction_msg.delChild('replace')
correction_msg.setTag('replace', attrs={'id': id_},
namespace=nbxmpp.NS_CORRECT)
id2 = self.connection.getAnID()
correction_msg.setID(id2)
correction_msg.setBody(msg)
if xhtml:
correction_msg.setXHTML(xhtml)
self.connection.send(correction_msg)
gajim.nec.push_incoming_event(MessageSentEvent(None, conn=self,
jid=jid, message=msg, keyID=None, chatstate=None))
if callback:
callback(correction_msg, msg)
return
if not xhtml and gajim.config.get('rst_formatting_outgoing_messages'):
from common.rst_xhtml_generator import create_xhtml
xhtml = create_xhtml(msg)
msg_iq = nbxmpp.Message(jid, msg, typ='groupchat', xhtml=xhtml)
if label is not None:
msg_iq.addChild(node = label)
msg_iq.addChild(node=label)
self.connection.send(msg_iq)
gajim.nec.push_incoming_event(MessageSentEvent(None, conn=self,
jid=jid, message=msg, keyID=None, chatstate=None))
if callback:
callback(msg_iq, msg)
def send_gc_subject(self, jid, subject):
if not gajim.account_is_connected(self.name):
......
......@@ -1248,6 +1248,7 @@ class DecryptedMessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
self.popup = False
self.msg_id = None # id in log database
self.attention = False # XEP-0224
self.correct_id = None # XEP-0308
self.receipt_request_tag = self.stanza.getTag('request',
namespace=nbxmpp.NS_RECEIPTS)
......@@ -1291,6 +1292,10 @@ class DecryptedMessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
self.msgtxt += _('URL:')
self.msgtxt += ' ' + self.oob_url
replace = self.stanza.getTag('replace', namespace=nbxmpp.NS_CORRECT)
if replace:
self.correct_id = replace.getAttr('id')
return True
class ChatstateReceivedEvent(nec.NetworkIncomingEvent):
......@@ -1318,6 +1323,7 @@ class GcMessageReceivedEvent(nec.NetworkIncomingEvent):
self.nickname = self.msg_obj.resource
self.timestamp = self.msg_obj.timestamp
self.xhtml_msgtxt = self.stanza.getXHTML()
self.correct_id = None # XEP-0308
if gajim.config.get('ignore_incoming_xhtml'):
self.xhtml_msgtxt = None
......@@ -1390,6 +1396,10 @@ class GcMessageReceivedEvent(nec.NetworkIncomingEvent):
[self.stanza, self.msg_obj], 0)
return
replace = self.stanza.getTag('replace', namespace=nbxmpp.NS_CORRECT)
if replace:
self.correct_id = replace.getAttr('id')
return True
class GcSubjectReceivedEvent(nec.NetworkIncomingEvent):
......@@ -2444,6 +2454,7 @@ class MessageOutgoingEvent(nec.NetworkOutgoingEvent):
self.is_loggable = True
self.control = None
self.attention = False
self.correction_msg = None
def generate(self):
return True
......
......@@ -212,7 +212,7 @@ gajim_common_features = [nbxmpp.NS_BYTESTREAM, nbxmpp.NS_SI, nbxmpp.NS_FILE,
nbxmpp.NS_SSN, nbxmpp.NS_MOOD, nbxmpp.NS_ACTIVITY, nbxmpp.NS_NICK,
nbxmpp.NS_ROSTERX, nbxmpp.NS_SECLABEL, nbxmpp.NS_HASHES,
nbxmpp.NS_HASHES_MD5, nbxmpp.NS_HASHES_SHA1, nbxmpp.NS_HASHES_SHA256,
nbxmpp.NS_HASHES_SHA512]
nbxmpp.NS_HASHES_SHA512, nbxmpp.NS_CORRECT]
# Optional features gajim supports per account
gajim_optional_features = {}
......
This diff is collapsed.
......@@ -1012,9 +1012,26 @@ class GroupchatControl(ChatControlBase):
tim=obj.timestamp, xhtml=None,
displaymarking=obj.displaymarking)
else:
if obj.nick in self.last_received_txt and obj.correct_id and \
obj.correct_id == self.last_received_id[obj.nick]:
if obj.nick == self.nick:
old_txt = self.last_sent_txt
self.last_sent_txt = obj.msgtxt
self.conv_textview.correct_last_sent_message(obj.msgtxt,
obj.xhtml_msgtxt, obj.nick, old_txt)
else:
old_txt = self.last_received_txt[obj.nick]
self.conv_textview.correct_last_received_message(obj.msgtxt,
obj.xhtml_msgtxt, obj.nick, old_txt)
self.last_received_txt[obj.nick] = obj.msgtxt
self.last_received_id[obj.nick] = obj.stanza.getID()
return
if obj.nick == self.nick:
self.last_sent_txt = obj.msgtxt
self.print_conversation(obj.msgtxt, contact=obj.nick,
tim=obj.timestamp, xhtml=obj.xhtml_msgtxt,
displaymarking=obj.displaymarking)
displaymarking=obj.displaymarking,
correct_id=(obj.stanza.getID(), None))
obj.needs_highlight = self.needs_visual_notification(obj.msgtxt)
def on_private_message(self, nick, msg, tim, xhtml, session, msg_id=None,
......@@ -1086,7 +1103,7 @@ class GroupchatControl(ChatControlBase):
displaymarking=displaymarking)
def print_conversation(self, text, contact='', tim=None, xhtml=None,
graphics=True, displaymarking=None):
graphics=True, displaymarking=None, correct_id=None):
"""
Print a line in the conversation
......@@ -1147,7 +1164,8 @@ class GroupchatControl(ChatControlBase):
ChatControlBase.print_conversation_line(self, text, kind, contact, tim,
other_tags_for_name, [], other_tags_for_text, xhtml=xhtml,
graphics=graphics, displaymarking=displaymarking)
graphics=graphics, displaymarking=displaymarking,
correct_id=correct_id)
def get_nb_unread(self):
type_events = ['printed_marked_gc_msg']
......@@ -1590,6 +1608,18 @@ class GroupchatControl(ChatControlBase):
else:
s = _('%(nick)s is now known as %(new_nick)s') % {
'nick': obj.nick, 'new_nick': obj.new_nick}
tv = self.conv_textview
if obj.nick in tv.last_received_message_marks:
tv.last_received_message_marks[obj.new_nick] = \
tv.last_received_message_marks[obj.nick]
del tv.last_received_message_marks[obj.nick]
if obj.nick in self.last_received_txt:
self.last_received_txt[obj.new_nick] = \
self.last_received_txt[obj.nick]
del self.last_received_txt[obj.nick]
self.last_received_id[obj.new_nick] = \
self.last_received_id[obj.nick]
del self.last_received_id[obj.nick]
# We add new nick to muc roster here, so we don't see
# that "new_nick has joined the room" when he just changed
# nick.
......@@ -1889,9 +1919,23 @@ class GroupchatControl(ChatControlBase):
if message != '' or message != '\n':
self.save_message(message, 'sent')
def _cb(msg, msg_txt):
# we'll save sent message text when we'll receive it in
# _nec_gc_message_received
self.last_sent_msg = msg
if self.correcting:
self.correcting = False
self.msg_textview.modify_base(Gtk.StateType.NORMAL,
self.old_message_tv_color)
if self.correcting and self.last_sent_msg:
correction_msg = self.last_sent_msg
else:
correction_msg = None
# Send the message
gajim.connections[self.account].send_gc_message(self.room_jid,
message, xhtml=xhtml, label=label)
message, xhtml=xhtml, label=label,
correction_msg=correction_msg, callback=_cb)
self.msg_textview.get_buffer().set_text('')
self.msg_textview.grab_focus()
......
......@@ -2719,7 +2719,7 @@ class RosterWindow:
obj.session.control.print_conversation(obj.msgtxt, typ,
tim=obj.timestamp, encrypted=obj.encrypted, subject=obj.subject,
xhtml=obj.xhtml, displaymarking=obj.displaymarking,
msg_id=obj.msg_id)
msg_id=obj.msg_id, correct_id=(obj.id_, obj.correct_id))
if obj.msg_id:
pw = obj.session.control.parent_win
end = obj.session.control.was_at_the_end
......
......@@ -99,7 +99,7 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession):
sectext = _('The database file (%s) cannot be read. Try to '
'repair it (see http://trac.gajim.org/wiki/DatabaseBackup) '
'or remove it (all history will be lost).') % \
common.logger.LOG_DB_PATH
gajim.logger.LOG_DB_PATH
gajim.nec.push_incoming_event(InformationEvent(None,
conn=self.conn, level='error', pri_txt=pritext,
sec_txt=sectext))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment