refactored the way certain messages are being found within a conversation

iNPUTmice created

Change summary

src/main/java/eu/siacs/conversations/entities/Conversation.java          | 114 
src/main/java/eu/siacs/conversations/entities/Message.java               |  10 
src/main/java/eu/siacs/conversations/services/XmppConnectionService.java | 151 
src/main/java/eu/siacs/conversations/ui/ConversationActivity.java        |   6 
src/main/java/eu/siacs/conversations/ui/ConversationFragment.java        |  29 
5 files changed, 193 insertions(+), 117 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/entities/Conversation.java 🔗

@@ -77,6 +77,104 @@ public class Conversation extends AbstractEntity {
 
 	private Bookmark bookmark;
 
+	public Message findUnsentMessageWithUuid(String uuid) {
+		synchronized(this.messages) {
+			for (final Message message : this.messages) {
+				final int s = message.getStatus();
+				if ((s == Message.STATUS_UNSEND || s == Message.STATUS_WAITING) && message.getUuid().equals(uuid)) {
+					return message;
+				}
+			}
+		}
+		return null;
+	}
+
+	public void findWaitingMessages(OnMessageFound onMessageFound) {
+		synchronized (this.messages) {
+			for(Message message : this.messages) {
+				if (message.getStatus() == Message.STATUS_WAITING) {
+					onMessageFound.onMessageFound(message);
+				}
+			}
+		}
+	}
+
+	public void findMessagesWithFiles(OnMessageFound onMessageFound) {
+		synchronized (this.messages) {
+			for (Message message : this.messages) {
+				if ((message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE)
+						&& message.getEncryption() != Message.ENCRYPTION_PGP) {
+					onMessageFound.onMessageFound(message);
+				}
+			}
+		}
+	}
+
+	public Message findMessageWithFileAndUuid(String uuid) {
+		synchronized (this.messages) {
+			for (Message message : this.messages) {
+				if (message.getType() == Message.TYPE_IMAGE
+						&& message.getEncryption() != Message.ENCRYPTION_PGP
+						&& message.getUuid().equals(uuid)) {
+					return message;
+				}
+			}
+		}
+		return null;
+	}
+
+	public void clearMessages() {
+		synchronized (this.messages) {
+			this.messages.clear();
+		}
+	}
+
+	public void findUnsentMessagesWithOtrEncryption(OnMessageFound onMessageFound) {
+		synchronized (this.messages) {
+			for (Message message : this.messages) {
+				if ((message.getStatus() == Message.STATUS_UNSEND || message.getStatus() == Message.STATUS_WAITING)
+						&& (message.getEncryption() == Message.ENCRYPTION_OTR)) {
+					onMessageFound.onMessageFound(message);
+				}
+			}
+		}
+	}
+
+	public void findUnsentTextMessages(OnMessageFound onMessageFound) {
+		synchronized (this.messages) {
+			for (Message message : this.messages) {
+				if (message.getType() != Message.TYPE_IMAGE
+						&& message.getStatus() == Message.STATUS_UNSEND) {
+					onMessageFound.onMessageFound(message);
+				}
+			}
+		}
+	}
+
+	public Message findSentMessageWithUuid(String uuid) {
+		synchronized (this.messages) {
+			for (Message message : this.messages) {
+				if (uuid.equals(message.getUuid())
+						|| (message.getStatus() >= Message.STATUS_SEND && uuid
+						.equals(message.getRemoteMsgId()))) {
+					return message;
+				}
+			}
+		}
+		return null;
+	}
+
+	public void populateWithMessages(List<Message> messages) {
+		synchronized (this.messages) {
+			messages.clear();
+			messages.addAll(this.messages);
+		}
+	}
+
+	public interface OnMessageFound {
+		public void onMessageFound(final Message message);
+	}
+
 	public Conversation(final String name, final Account account, final Jid contactJid,
 			final int mode) {
 		this(java.util.UUID.randomUUID().toString(), name, null, account
@@ -103,10 +201,6 @@ public class Conversation extends AbstractEntity {
 		}
 	}
 
-	public List<Message> getMessages() {
-		return messages;
-	}
-
 	public boolean isRead() {
         return (this.messages == null) || (this.messages.size() == 0) || this.messages.get(this.messages.size() - 1).isRead();
     }
@@ -455,9 +549,11 @@ public class Conversation extends AbstractEntity {
 	}
 
 	public boolean hasDuplicateMessage(Message message) {
-		for (int i = this.getMessages().size() - 1; i >= 0; --i) {
-			if (this.messages.get(i).equals(message)) {
-				return true;
+		synchronized (this.messages) {
+			for (int i = this.messages.size() - 1; i >= 0; --i) {
+				if (this.messages.get(i).equals(message)) {
+					return true;
+				}
 			}
 		}
 		return false;
@@ -465,7 +561,7 @@ public class Conversation extends AbstractEntity {
 
 	public Message findSentMessageWithBody(String body) {
 		synchronized (this.messages) {
-			for (int i = this.getMessages().size() - 1; i >= 0; --i) {
+			for (int i = this.messages.size() - 1; i >= 0; --i) {
 				Message message = this.messages.get(i);
 				if ((message.getStatus() == Message.STATUS_UNSEND || message.getStatus() == Message.STATUS_SEND) && message.getBody() != null && message.getBody().equals(body)) {
 					return message;
@@ -567,7 +663,7 @@ public class Conversation extends AbstractEntity {
 
 	public void sort() {
 		synchronized (this.messages) {
-			Collections.sort(this.messages,new Comparator<Message>() {
+			Collections.sort(this.messages, new Comparator<Message>() {
 				@Override
 				public int compare(Message left, Message right) {
 					if (left.getTimeSent() < right.getTimeSent()) {

src/main/java/eu/siacs/conversations/entities/Message.java 🔗

@@ -323,12 +323,10 @@ public class Message extends AbstractEntity {
 		synchronized (this.conversation.messages) {
 			if (this.mNextMessage == null) {
 				int index = this.conversation.messages.indexOf(this);
-				if (index < 0
-						|| index >= this.conversation.getMessages().size() - 1) {
+				if (index < 0 || index >= this.conversation.messages.size() - 1) {
 					this.mNextMessage = null;
 				} else {
-					this.mNextMessage = this.conversation.messages
-							.get(index + 1);
+					this.mNextMessage = this.conversation.messages.get(index + 1);
 				}
 			}
 			return this.mNextMessage;
@@ -338,13 +336,11 @@ public class Message extends AbstractEntity {
 	public Message prev() {
 		synchronized (this.conversation.messages) {
 			if (this.mPreviousMessage == null) {
-
 				int index = this.conversation.messages.indexOf(this);
 				if (index <= 0 || index > this.conversation.messages.size()) {
 					this.mPreviousMessage = null;
 				} else {
-					this.mPreviousMessage = this.conversation.messages
-							.get(index - 1);
+					this.mPreviousMessage = this.conversation.messages.get(index - 1);
 				}
 			}
 			return this.mPreviousMessage;

src/main/java/eu/siacs/conversations/services/XmppConnectionService.java 🔗

@@ -120,7 +120,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 					conversation.resetOtrSession();
 				}
 				if (online && (contact.getPresences().size() == 1)) {
-					sendUnsendMessages(conversation);
+					sendUnsentMessages(conversation);
 				}
 			}
 		}
@@ -165,7 +165,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 				for (Conversation conversation : conversations) {
 					if (conversation.getAccount() == account) {
 						conversation.startOtrIfNeeded();
-						sendUnsendMessages(conversation);
+						sendUnsentMessages(conversation);
 					}
 				}
 				if (connection != null && connection.getFeatures().csi()) {
@@ -258,14 +258,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 		public void onMessageAcknowledged(Account account, String uuid) {
 			for (final Conversation conversation : getConversations()) {
 				if (conversation.getAccount() == account) {
-					for (final Message message : conversation.getMessages()) {
-						final int s = message.getStatus();
-						if ((s == Message.STATUS_UNSEND || s == Message.STATUS_WAITING) && message.getUuid().equals(uuid)) {
-							markMessage(message, Message.STATUS_SEND);
-							if (conversation.setLastMessageTransmitted(System.currentTimeMillis())) {
-								databaseBackend.updateConversation(conversation);
-							}
-							return;
+					Message message = conversation.findUnsentMessageWithUuid(uuid);
+					if (message != null) {
+						markMessage(message, Message.STATUS_SEND);
+						if (conversation.setLastMessageTransmitted(System.currentTimeMillis())) {
+							databaseBackend.updateConversation(conversation);
 						}
 					}
 				}
@@ -640,12 +637,22 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 					}
 				} else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
 					message.getConversation().endOtrIfNeeded();
-					failWaitingOtrMessages(message.getConversation());
+					message.getConversation().findUnsentMessagesWithOtrEncryption(new Conversation.OnMessageFound() {
+						@Override
+						public void onMessageFound(Message message) {
+							markMessage(message,Message.STATUS_SEND_FAILED);
+						}
+					});
 					packet = mMessageGenerator.generatePgpChat(message);
 					send = true;
 				} else {
 					message.getConversation().endOtrIfNeeded();
-					failWaitingOtrMessages(message.getConversation());
+					message.getConversation().findUnsentMessagesWithOtrEncryption(new Conversation.OnMessageFound() {
+						@Override
+						public void onMessageFound(Message message) {
+							markMessage(message,Message.STATUS_SEND_FAILED);
+						}
+					});
 					packet = mMessageGenerator.generateChat(message);
 					send = true;
 				}
@@ -688,13 +695,14 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 		updateConversationUi();
 	}
 
-	private void sendUnsendMessages(Conversation conversation) {
-		for (int i = 0; i < conversation.getMessages().size(); ++i) {
-			int status = conversation.getMessages().get(i).getStatus();
-			if (status == Message.STATUS_WAITING) {
-				resendMessage(conversation.getMessages().get(i));
+	private void sendUnsentMessages(Conversation conversation) {
+		conversation.findWaitingMessages(new Conversation.OnMessageFound() {
+
+			@Override
+			public void onMessageFound(Message message) {
+				resendMessage(message);
 			}
-		}
+		});
 	}
 
 	private void resendMessage(Message message) {
@@ -898,28 +906,26 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 	}
 
 	private void checkDeletedFiles(Conversation conversation) {
-		for (Message message : conversation.getMessages()) {
-			if ((message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE)
-					&& message.getEncryption() != Message.ENCRYPTION_PGP) {
+		conversation.findMessagesWithFiles(new Conversation.OnMessageFound() {
+
+			@Override
+			public void onMessageFound(Message message) {
 				if (!getFileBackend().isFileAvailable(message)) {
 					message.setDownloadable(new DownloadablePlaceholder(Downloadable.STATUS_DELETED));
 				}
-					}
-		}
+			}
+		});
 	}
 
 	private void markFileDeleted(String uuid) {
 		for (Conversation conversation : getConversations()) {
-			for (Message message : conversation.getMessages()) {
-				if (message.getType() == Message.TYPE_IMAGE
-						&& message.getEncryption() != Message.ENCRYPTION_PGP
-						&& message.getUuid().equals(uuid)) {
-					if (!getFileBackend().isFileAvailable(message)) {
-						message.setDownloadable(new DownloadablePlaceholder(Downloadable.STATUS_DELETED));
-						updateConversationUi();
-					}
-					return;
-						}
+			Message message = conversation.findMessageWithFileAndUuid(uuid);
+			if (message != null) {
+				if (!getFileBackend().isFileAvailable(message)) {
+					message.setDownloadable(new DownloadablePlaceholder(Downloadable.STATUS_DELETED));
+					updateConversationUi();
+				}
+				return;
 			}
 		}
 	}
@@ -1067,12 +1073,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 		}
 	}
 
-	public void clearConversationHistory(Conversation conversation) {
-		this.databaseBackend.deleteMessagesInConversation(conversation);
-		conversation.getMessages().clear();
-		updateConversationUi();
-	}
-
 	public void createAccount(Account account) {
 		account.initOtrEngine(this);
 		databaseBackend.createAccount(account);
@@ -1533,36 +1533,35 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 	}
 
 	public void onOtrSessionEstablished(Conversation conversation) {
-		Account account = conversation.getAccount();
-		List<Message> messages = conversation.getMessages();
-		Session otrSession = conversation.getOtrSession();
+		final Account account = conversation.getAccount();
+		final Session otrSession = conversation.getOtrSession();
 		Log.d(Config.LOGTAG,
 				account.getJid().toBareJid() + " otr session established with "
-				+ conversation.getContactJid() + "/"
-				+ otrSession.getSessionID().getUserID());
-		for (Message msg : messages) {
-			if ((msg.getStatus() == Message.STATUS_UNSEND || msg.getStatus() == Message.STATUS_WAITING)
-					&& (msg.getEncryption() == Message.ENCRYPTION_OTR)) {
+						+ conversation.getContactJid() + "/"
+						+ otrSession.getSessionID().getUserID());
+		conversation.findUnsentMessagesWithOtrEncryption(new Conversation.OnMessageFound() {
+
+			@Override
+			public void onMessageFound(Message message) {
 				SessionID id = otrSession.getSessionID();
 				try {
-					msg.setCounterpart(Jid.fromString(id.getAccountID() + "/" + id.getUserID()));
+					message.setCounterpart(Jid.fromString(id.getAccountID() + "/" + id.getUserID()));
 				} catch (InvalidJidException e) {
-					break;
+					return;
 				}
-				if (msg.getType() == Message.TYPE_TEXT) {
-					MessagePacket outPacket = mMessageGenerator
-						.generateOtrChat(msg, true);
+				if (message.getType() == Message.TYPE_TEXT) {
+					MessagePacket outPacket = mMessageGenerator.generateOtrChat(message, true);
 					if (outPacket != null) {
-						msg.setStatus(Message.STATUS_SEND);
-						databaseBackend.updateMessage(msg);
+						message.setStatus(Message.STATUS_SEND);
+						databaseBackend.updateMessage(message);
 						sendMessagePacket(account, outPacket);
 					}
-				} else if (msg.getType() == Message.TYPE_IMAGE || msg.getType() == Message.TYPE_FILE) {
-					mJingleConnectionManager.createNewConnection(msg);
+				} else if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) {
+					mJingleConnectionManager.createNewConnection(message);
 				}
-					}
-		}
-		updateConversationUi();
+				updateConversationUi();
+			}
+		});
 	}
 
 	public boolean renewSymmetricKey(Conversation conversation) {
@@ -1817,12 +1816,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 	public void resetSendingToWaiting(Account account) {
 		for (Conversation conversation : getConversations()) {
 			if (conversation.getAccount() == account) {
-				for (Message message : conversation.getMessages()) {
-					if (message.getType() != Message.TYPE_IMAGE
-							&& message.getStatus() == Message.STATUS_UNSEND) {
+				conversation.findUnsentTextMessages(new Conversation.OnMessageFound() {
+
+					@Override
+					public void onMessageFound(Message message) {
 						markMessage(message, Message.STATUS_WAITING);
-							}
-				}
+					}
+				});
 			}
 		}
 	}
@@ -1847,15 +1847,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 		if (uuid == null) {
 			return false;
 		} else {
-			for (Message message : conversation.getMessages()) {
-				if (uuid.equals(message.getUuid())
-						|| (message.getStatus() >= Message.STATUS_SEND && uuid
-							.equals(message.getRemoteMsgId()))) {
-					markMessage(message, status);
-					return true;
-							}
+			Message message = conversation.findSentMessageWithUuid(uuid);
+			if (message!=null) {
+				markMessage(message,status);
+				return true;
+			} else {
+				return false;
 			}
-			return false;
 		}
 	}
 
@@ -1949,15 +1947,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 		}
 	}
 
-	public void failWaitingOtrMessages(Conversation conversation) {
-		for (Message message : conversation.getMessages()) {
-			if (message.getEncryption() == Message.ENCRYPTION_OTR
-					&& message.getStatus() == Message.STATUS_WAITING) {
-				markMessage(message, Message.STATUS_SEND_FAILED);
-					}
-		}
-	}
-
 	public SecureRandom getRNG() {
 		return this.mRandom;
 	}

src/main/java/eu/siacs/conversations/ui/ConversationActivity.java 🔗

@@ -491,10 +491,12 @@ public class ConversationActivity extends XmppActivity implements
 
 					@Override
 					public void onClick(DialogInterface dialog, int which) {
-						ConversationActivity.this.xmppConnectionService
-								.clearConversationHistory(conversation);
+						conversation.clearMessages();
 						if (endConversationCheckBox.isChecked()) {
 							endConversation(conversation);
+						} else {
+							updateConversationList();
+							ConversationActivity.this.mConversationFragment.updateMessages();
 						}
 					}
 				});

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java 🔗

@@ -120,8 +120,7 @@ public class ConversationFragment extends Fragment {
 					long timestamp = ConversationFragment.this.messageList.get(0).getTimeSent();
 					messagesLoaded = false;
 					int size = activity.xmppConnectionService.loadMoreMessages(conversation, timestamp);
-					ConversationFragment.this.messageList.clear();
-					ConversationFragment.this.messageList.addAll(conversation.getMessages());
+					conversation.populateWithMessages(ConversationFragment.this.messageList);
 					updateStatusMessages();
 					messageListAdapter.notifyDataSetChanged();
 					if (size != 0) {
@@ -580,25 +579,19 @@ public class ConversationFragment extends Fragment {
 							break;
 					}
 				}
-				this.messageList.clear();
-				if (this.conversation.getMessages().size() == 0) {
-					messagesLoaded = false;
-				} else {
-					this.messageList.addAll(this.conversation.getMessages());
-					messagesLoaded = true;
-					for (Message message : this.messageList) {
-						if (message.getEncryption() == Message.ENCRYPTION_PGP
-								&& (message.getStatus() == Message.STATUS_RECEIVED || message
-								.getStatus() >= Message.STATUS_SEND)
-								&& message.getDownloadable() == null) {
-							if (!mEncryptedMessages.contains(message)) {
-								mEncryptedMessages.add(message);
-							}
+				conversation.populateWithMessages(ConversationFragment.this.messageList);
+				for (Message message : this.messageList) {
+					if (message.getEncryption() == Message.ENCRYPTION_PGP
+							&& (message.getStatus() == Message.STATUS_RECEIVED || message
+							.getStatus() >= Message.STATUS_SEND)
+							&& message.getDownloadable() == null) {
+						if (!mEncryptedMessages.contains(message)) {
+							mEncryptedMessages.add(message);
 						}
 					}
-					decryptNext();
-					updateStatusMessages();
 				}
+				decryptNext();
+				updateStatusMessages();
 				this.messageListAdapter.notifyDataSetChanged();
 				updateChatMsgHint();
 				if (!activity.isConversationsOverviewVisable() || !activity.isConversationsOverviewHideable()) {