use stanza-id for display markers in group chats
This commit is contained in:
		
							parent
							
								
									27bf871472
								
							
						
					
					
						commit
						8183c54ba0
					
				|  | @ -51,16 +51,16 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl | ||||||
|     public static final String ATTRIBUTE_ALWAYS_NOTIFY = "always_notify"; |     public static final String ATTRIBUTE_ALWAYS_NOTIFY = "always_notify"; | ||||||
|     public static final String ATTRIBUTE_PUSH_NODE = "push_node"; |     public static final String ATTRIBUTE_PUSH_NODE = "push_node"; | ||||||
|     public static final String ATTRIBUTE_LAST_CLEAR_HISTORY = "last_clear_history"; |     public static final String ATTRIBUTE_LAST_CLEAR_HISTORY = "last_clear_history"; | ||||||
|  |     public static final String ATTRIBUTE_FORMERLY_PRIVATE_NON_ANONYMOUS = "formerly_private_non_anonymous"; | ||||||
|     static final String ATTRIBUTE_MUC_PASSWORD = "muc_password"; |     static final String ATTRIBUTE_MUC_PASSWORD = "muc_password"; | ||||||
|  |     static final String ATTRIBUTE_MEMBERS_ONLY = "members_only"; | ||||||
|  |     static final String ATTRIBUTE_MODERATED = "moderated"; | ||||||
|  |     static final String ATTRIBUTE_NON_ANONYMOUS = "non_anonymous"; | ||||||
|     private static final String ATTRIBUTE_NEXT_MESSAGE = "next_message"; |     private static final String ATTRIBUTE_NEXT_MESSAGE = "next_message"; | ||||||
|     private static final String ATTRIBUTE_NEXT_MESSAGE_TIMESTAMP = "next_message_timestamp"; |     private static final String ATTRIBUTE_NEXT_MESSAGE_TIMESTAMP = "next_message_timestamp"; | ||||||
|     private static final String ATTRIBUTE_CRYPTO_TARGETS = "crypto_targets"; |     private static final String ATTRIBUTE_CRYPTO_TARGETS = "crypto_targets"; | ||||||
|     private static final String ATTRIBUTE_NEXT_ENCRYPTION = "next_encryption"; |     private static final String ATTRIBUTE_NEXT_ENCRYPTION = "next_encryption"; | ||||||
|     private static final String ATTRIBUTE_CORRECTING_MESSAGE = "correcting_message"; |     private static final String ATTRIBUTE_CORRECTING_MESSAGE = "correcting_message"; | ||||||
| 	static final String ATTRIBUTE_MEMBERS_ONLY = "members_only"; |  | ||||||
| 	static final String ATTRIBUTE_MODERATED = "moderated"; |  | ||||||
| 	static final String ATTRIBUTE_NON_ANONYMOUS = "non_anonymous"; |  | ||||||
| 	public static final String ATTRIBUTE_FORMERLY_PRIVATE_NON_ANONYMOUS = "formerly_private_non_anonymous"; |  | ||||||
|     protected final ArrayList<Message> messages = new ArrayList<>(); |     protected final ArrayList<Message> messages = new ArrayList<>(); | ||||||
|     public AtomicBoolean messagesLoaded = new AtomicBoolean(true); |     public AtomicBoolean messagesLoaded = new AtomicBoolean(true); | ||||||
|     protected Account account = null; |     protected Account account = null; | ||||||
|  | @ -118,6 +118,33 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl | ||||||
|                 cursor.getString(cursor.getColumnIndex(ATTRIBUTES))); |                 cursor.getString(cursor.getColumnIndex(ATTRIBUTES))); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public static Message getLatestMarkableMessage(final List<Message> messages, boolean isPrivateAndNonAnonymousMuc) { | ||||||
|  |         for (int i = messages.size() - 1; i >= 0; --i) { | ||||||
|  |             final Message message = messages.get(i); | ||||||
|  |             if (message.getStatus() <= Message.STATUS_RECEIVED | ||||||
|  |                     && (message.markable || isPrivateAndNonAnonymousMuc) | ||||||
|  |                     && !message.isPrivateMessage()) { | ||||||
|  |                 return message; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static boolean suitableForOmemoByDefault(final Conversation conversation) { | ||||||
|  |         if (conversation.getJid().asBareJid().equals(Config.BUG_REPORTS)) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         if (conversation.getContact().isOwnServer()) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         final String contact = conversation.getJid().getDomain(); | ||||||
|  |         final String account = conversation.getAccount().getServer(); | ||||||
|  |         if (Config.OMEMO_EXCEPTIONS.CONTACT_DOMAINS.contains(contact) || Config.OMEMO_EXCEPTIONS.ACCOUNT_DOMAINS.contains(account)) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         return conversation.isSingleOrPrivateAndNonAnonymous() || conversation.getBooleanAttribute(ATTRIBUTE_FORMERLY_PRIVATE_NON_ANONYMOUS, false); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public boolean hasMessagesLeftOnServer() { |     public boolean hasMessagesLeftOnServer() { | ||||||
|         return messagesLeftOnServer; |         return messagesLeftOnServer; | ||||||
|     } |     } | ||||||
|  | @ -351,6 +378,17 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl | ||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public Message findMessageWithServerMsgId(String id) { | ||||||
|  |         synchronized (this.messages) { | ||||||
|  |             for (Message message : this.messages) { | ||||||
|  |                 if (id != null && id.equals(message.getServerMsgId())) { | ||||||
|  |                     return message; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public boolean hasMessageWithCounterpart(Jid counterpart) { |     public boolean hasMessageWithCounterpart(Jid counterpart) { | ||||||
|         synchronized (this.messages) { |         synchronized (this.messages) { | ||||||
|             for (Message message : this.messages) { |             for (Message message : this.messages) { | ||||||
|  | @ -484,18 +522,6 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl | ||||||
|         return unread; |         return unread; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 	public static Message getLatestMarkableMessage(final List<Message> messages, boolean isPrivateAndNonAnonymousMuc) { |  | ||||||
| 			for (int i = messages.size() - 1; i >= 0; --i) { |  | ||||||
| 				final Message message = messages.get(i); |  | ||||||
| 				if (message.getStatus() <= Message.STATUS_RECEIVED |  | ||||||
| 						&& (message.markable || isPrivateAndNonAnonymousMuc) |  | ||||||
| 						&& !message.isPrivateMessage()) { |  | ||||||
| 					return message; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		return null; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
|     public Message getLatestMessage() { |     public Message getLatestMessage() { | ||||||
|         synchronized (this.messages) { |         synchronized (this.messages) { | ||||||
|             if (this.messages.size() == 0) { |             if (this.messages.size() == 0) { | ||||||
|  | @ -509,7 +535,8 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 	public @NonNull CharSequence getName() { |     public @NonNull | ||||||
|  |     CharSequence getName() { | ||||||
|         if (getMode() == MODE_MULTI) { |         if (getMode() == MODE_MULTI) { | ||||||
|             final String roomName = getMucOptions().getName(); |             final String roomName = getMucOptions().getName(); | ||||||
|             final String subject = getMucOptions().getSubject(); |             final String subject = getMucOptions().getSubject(); | ||||||
|  | @ -648,21 +675,6 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 	private static boolean suitableForOmemoByDefault(final Conversation conversation) { |  | ||||||
| 		if (conversation.getJid().asBareJid().equals(Config.BUG_REPORTS)) { |  | ||||||
| 			return false; |  | ||||||
| 		} |  | ||||||
| 		if (conversation.getContact().isOwnServer()) { |  | ||||||
| 			return false; |  | ||||||
| 		} |  | ||||||
| 		final String contact = conversation.getJid().getDomain(); |  | ||||||
| 		final String account = conversation.getAccount().getServer(); |  | ||||||
| 		if (Config.OMEMO_EXCEPTIONS.CONTACT_DOMAINS.contains(contact) || Config.OMEMO_EXCEPTIONS.ACCOUNT_DOMAINS.contains(account)) { |  | ||||||
| 			return false; |  | ||||||
| 		} |  | ||||||
| 		return conversation.isSingleOrPrivateAndNonAnonymous() || conversation.getBooleanAttribute(ATTRIBUTE_FORMERLY_PRIVATE_NON_ANONYMOUS, false); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
|     public boolean setNextEncryption(int encryption) { |     public boolean setNextEncryption(int encryption) { | ||||||
|         return this.setAttribute(ATTRIBUTE_NEXT_ENCRYPTION, encryption); |         return this.setAttribute(ATTRIBUTE_NEXT_ENCRYPTION, encryption); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ import eu.siacs.conversations.crypto.axolotl.AxolotlService; | ||||||
| import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage; | import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage; | ||||||
| import eu.siacs.conversations.entities.Account; | import eu.siacs.conversations.entities.Account; | ||||||
| import eu.siacs.conversations.entities.Conversation; | import eu.siacs.conversations.entities.Conversation; | ||||||
|  | import eu.siacs.conversations.entities.Conversational; | ||||||
| import eu.siacs.conversations.entities.Message; | import eu.siacs.conversations.entities.Message; | ||||||
| import eu.siacs.conversations.http.P1S3UrlStreamHandler; | import eu.siacs.conversations.http.P1S3UrlStreamHandler; | ||||||
| import eu.siacs.conversations.services.XmppConnectionService; | import eu.siacs.conversations.services.XmppConnectionService; | ||||||
|  | @ -160,15 +161,23 @@ public class MessageGenerator extends AbstractGenerator { | ||||||
|         return packet; |         return packet; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public MessagePacket confirm(final Account account, final Jid to, final String id, final Jid counterpart, final boolean groupChat) { |     public MessagePacket confirm(final Message message) { | ||||||
|         MessagePacket packet = new MessagePacket(); |         final boolean groupChat = message.getConversation().getMode() == Conversational.MODE_MULTI; | ||||||
|  |         final Jid to = message.getCounterpart(); | ||||||
|  |         final MessagePacket packet = new MessagePacket(); | ||||||
|         packet.setType(groupChat ? MessagePacket.TYPE_GROUPCHAT : MessagePacket.TYPE_CHAT); |         packet.setType(groupChat ? MessagePacket.TYPE_GROUPCHAT : MessagePacket.TYPE_CHAT); | ||||||
|         packet.setTo(groupChat ? to.asBareJid() : to); |         packet.setTo(groupChat ? to.asBareJid() : to); | ||||||
|         packet.setFrom(account.getJid()); |         final Element displayed = packet.addChild("displayed", "urn:xmpp:chat-markers:0"); | ||||||
|         Element displayed = packet.addChild("displayed", "urn:xmpp:chat-markers:0"); |         if (groupChat) { | ||||||
|         displayed.setAttribute("id", id); |             final String stanzaId = message.getServerMsgId(); | ||||||
|         if (groupChat && counterpart != null) { |             if (stanzaId != null) { | ||||||
|             displayed.setAttribute("sender", counterpart.toString()); |                 displayed.setAttribute("id", stanzaId); | ||||||
|  |             } else { | ||||||
|  |                 displayed.setAttribute("sender", to.toString()); | ||||||
|  |                 displayed.setAttribute("id", message.getRemoteMsgId()); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             displayed.setAttribute("id", message.getRemoteMsgId()); | ||||||
|         } |         } | ||||||
|         packet.addChild("store", "urn:xmpp:hints"); |         packet.addChild("store", "urn:xmpp:hints"); | ||||||
|         return packet; |         return packet; | ||||||
|  |  | ||||||
|  | @ -927,9 +927,17 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece | ||||||
|                     activateGracePeriod(account); |                     activateGracePeriod(account); | ||||||
|                 } |                 } | ||||||
|             } else if (isTypeGroupChat) { |             } else if (isTypeGroupChat) { | ||||||
|                 Conversation conversation = mXmppConnectionService.find(account, counterpart.asBareJid()); |                 final Conversation conversation = mXmppConnectionService.find(account, counterpart.asBareJid()); | ||||||
|                 if (conversation != null && id != null && sender != null) { |                 final Message message; | ||||||
|                     Message message = conversation.findMessageWithRemoteId(id, sender); |                 if (conversation != null && id != null) { | ||||||
|  |                     if (sender != null) { | ||||||
|  |                         message = conversation.findMessageWithRemoteId(id, sender); | ||||||
|  |                     } else { | ||||||
|  |                         message = conversation.findMessageWithServerMsgId(id); | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     message = null; | ||||||
|  |                 } | ||||||
|                 if (message != null) { |                 if (message != null) { | ||||||
|                     final Jid fallback = conversation.getMucOptions().getTrueCounterpart(counterpart); |                     final Jid fallback = conversation.getMucOptions().getTrueCounterpart(counterpart); | ||||||
|                     final Jid trueJid = getTrueCounterpart((query != null && query.safeToExtractTrueCounterpart()) ? mucUserElement : null, fallback); |                     final Jid trueJid = getTrueCounterpart((query != null && query.safeToExtractTrueCounterpart()) ? mucUserElement : null, fallback); | ||||||
|  | @ -945,7 +953,6 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 } |  | ||||||
|             } else { |             } else { | ||||||
|                 final Message displayedMessage = mXmppConnectionService.markMessage(account, from.asBareJid(), id, Message.STATUS_SEND_DISPLAYED); |                 final Message displayedMessage = mXmppConnectionService.markMessage(account, from.asBareJid(), id, Message.STATUS_SEND_DISPLAYED); | ||||||
|                 Message message = displayedMessage == null ? null : displayedMessage.prev(); |                 Message message = displayedMessage == null ? null : displayedMessage.prev(); | ||||||
|  |  | ||||||
|  | @ -4062,6 +4062,7 @@ public class XmppConnectionService extends Service { | ||||||
|                 } |                 } | ||||||
|             }; |             }; | ||||||
|             mDatabaseWriterExecutor.execute(runnable); |             mDatabaseWriterExecutor.execute(runnable); | ||||||
|  |             updateConversationUi(); | ||||||
|             updateUnreadCountBadge(); |             updateUnreadCountBadge(); | ||||||
|             return readMessages; |             return readMessages; | ||||||
|         } else { |         } else { | ||||||
|  | @ -4094,11 +4095,9 @@ public class XmppConnectionService extends Service { | ||||||
|                 && (markable.trusted() || isPrivateAndNonAnonymousMuc) |                 && (markable.trusted() || isPrivateAndNonAnonymousMuc) | ||||||
|                 && markable.getRemoteMsgId() != null) { |                 && markable.getRemoteMsgId() != null) { | ||||||
|             Log.d(Config.LOGTAG, conversation.getAccount().getJid().asBareJid() + ": sending read marker to " + markable.getCounterpart().toString()); |             Log.d(Config.LOGTAG, conversation.getAccount().getJid().asBareJid() + ": sending read marker to " + markable.getCounterpart().toString()); | ||||||
|             Account account = conversation.getAccount(); |             final Account account = conversation.getAccount(); | ||||||
|             final Jid to = markable.getCounterpart(); |             final MessagePacket packet = mMessageGenerator.confirm(markable); | ||||||
|             final boolean groupChat = conversation.getMode() == Conversation.MODE_MULTI; |             this.sendMessagePacket(account, packet); | ||||||
|             MessagePacket packet = mMessageGenerator.confirm(account, to, markable.getRemoteMsgId(), markable.getCounterpart(), groupChat); |  | ||||||
|             this.sendMessagePacket(conversation.getAccount(), packet); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Daniel Gultsch
						Daniel Gultsch