Tag carbon messages in parser, adapt session logic

Andreas Straub created

Messages sent from another device of the own account are now explicitly
tagged as carboned message. The session detection logic now uses this
tag to find "session borders".

Change summary

src/main/java/eu/siacs/conversations/entities/Message.java            | 24 
src/main/java/eu/siacs/conversations/parser/MessageParser.java        |  5 
src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java |  6 
src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java   |  4 
4 files changed, 32 insertions(+), 7 deletions(-)

Detailed changes

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

@@ -51,6 +51,7 @@ public class Message extends AbstractEntity {
 	public static final String ENCRYPTION = "encryption";
 	public static final String STATUS = "status";
 	public static final String TYPE = "type";
+	public static final String CARBON = "carbon";
 	public static final String REMOTE_MSG_ID = "remoteMsgId";
 	public static final String SERVER_MSG_ID = "serverMsgId";
 	public static final String RELATIVE_FILE_PATH = "relativeFilePath";
@@ -68,6 +69,7 @@ public class Message extends AbstractEntity {
 	protected int encryption;
 	protected int status;
 	protected int type;
+	protected boolean carbon = false;
 	protected String relativeFilePath;
 	protected boolean read = true;
 	protected String remoteMsgId = null;
@@ -85,8 +87,11 @@ public class Message extends AbstractEntity {
 	public Message(Conversation conversation, String body, int encryption) {
 		this(conversation, body, encryption, STATUS_UNSEND);
 	}
-
 	public Message(Conversation conversation, String body, int encryption, int status) {
+		this(conversation, body, encryption, status, false);
+	}
+
+	public Message(Conversation conversation, String body, int encryption, int status, boolean carbon) {
 		this(java.util.UUID.randomUUID().toString(),
 				conversation.getUuid(),
 				conversation.getJid() == null ? null : conversation.getJid().toBareJid(),
@@ -96,6 +101,7 @@ public class Message extends AbstractEntity {
 				encryption,
 				status,
 				TYPE_TEXT,
+				false,
 				null,
 				null,
 				null,
@@ -105,8 +111,9 @@ public class Message extends AbstractEntity {
 
 	private Message(final String uuid, final String conversationUUid, final Jid counterpart,
 					final Jid trueCounterpart, final String body, final long timeSent,
-					final int encryption, final int status, final int type, final String remoteMsgId,
-					final String relativeFilePath, final String serverMsgId, final String fingerprint) {
+					final int encryption, final int status, final int type, final boolean carbon,
+					final String remoteMsgId, final String relativeFilePath,
+					final String serverMsgId, final String fingerprint) {
 		this.uuid = uuid;
 		this.conversationUuid = conversationUUid;
 		this.counterpart = counterpart;
@@ -116,6 +123,7 @@ public class Message extends AbstractEntity {
 		this.encryption = encryption;
 		this.status = status;
 		this.type = type;
+		this.carbon = carbon;
 		this.remoteMsgId = remoteMsgId;
 		this.relativeFilePath = relativeFilePath;
 		this.serverMsgId = serverMsgId;
@@ -154,6 +162,7 @@ public class Message extends AbstractEntity {
 				cursor.getInt(cursor.getColumnIndex(ENCRYPTION)),
 				cursor.getInt(cursor.getColumnIndex(STATUS)),
 				cursor.getInt(cursor.getColumnIndex(TYPE)),
+				cursor.getInt(cursor.getColumnIndex(CARBON))>0,
 				cursor.getString(cursor.getColumnIndex(REMOTE_MSG_ID)),
 				cursor.getString(cursor.getColumnIndex(RELATIVE_FILE_PATH)),
 				cursor.getString(cursor.getColumnIndex(SERVER_MSG_ID)),
@@ -188,6 +197,7 @@ public class Message extends AbstractEntity {
 		values.put(ENCRYPTION, encryption);
 		values.put(STATUS, status);
 		values.put(TYPE, type);
+		values.put(CARBON, carbon ? 1 : 0);
 		values.put(REMOTE_MSG_ID, remoteMsgId);
 		values.put(RELATIVE_FILE_PATH, relativeFilePath);
 		values.put(SERVER_MSG_ID, serverMsgId);
@@ -312,6 +322,14 @@ public class Message extends AbstractEntity {
 		this.type = type;
 	}
 
+	public boolean isCarbon() {
+		return carbon;
+	}
+
+	public void setCarbon(boolean carbon) {
+		this.carbon = carbon;
+	}
+
 	public void setTrueCounterpart(Jid trueCounterpart) {
 		this.trueCounterpart = trueCounterpart;
 	}

src/main/java/eu/siacs/conversations/parser/MessageParser.java 🔗

@@ -230,6 +230,7 @@ public class MessageParser extends AbstractParser implements
 		final MessagePacket packet;
 		Long timestamp = null;
 		final boolean isForwarded;
+		boolean isCarbon = false;
 		String serverMsgId = null;
 		final Element fin = original.findChild("fin", "urn:xmpp:mam:0");
 		if (fin != null) {
@@ -260,7 +261,8 @@ public class MessageParser extends AbstractParser implements
 				return;
 			}
 			timestamp = f != null ? f.second : null;
-			isForwarded = f != null;
+			isCarbon = f != null;
+			isForwarded = isCarbon;
 		} else {
 			packet = original;
 			isForwarded = false;
@@ -346,6 +348,7 @@ public class MessageParser extends AbstractParser implements
 			message.setCounterpart(counterpart);
 			message.setRemoteMsgId(remoteMsgId);
 			message.setServerMsgId(serverMsgId);
+			message.setCarbon(isCarbon);
 			message.setTime(timestamp);
 			message.markable = packet.hasChild("markable", "urn:xmpp:chat-markers:0");
 			if (conversation.getMode() == Conversation.MODE_MULTI) {

src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java 🔗

@@ -41,7 +41,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
 	private static DatabaseBackend instance = null;
 
 	private static final String DATABASE_NAME = "history";
-	private static final int DATABASE_VERSION = 15;
+	private static final int DATABASE_VERSION = 16;
 
 	private static String CREATE_CONTATCS_STATEMENT = "create table "
 			+ Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, "
@@ -295,6 +295,10 @@ public class DatabaseBackend extends SQLiteOpenHelper {
 			db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN "
 					+ Message.FINGERPRINT + " TEXT");
 		}
+		if (oldVersion < 16 && newVersion >= 16) {
+			db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN "
+					+ Message.CARBON + " INTEGER");
+		}
 	}
 
 	public static synchronized DatabaseBackend getInstance(Context context) {

src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java 🔗

@@ -567,7 +567,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 					wasEncrypted = true;
 					break;
 				}
-				if (iterator.getRemoteMsgId() == null && iterator.getType() == SENT) {
+				if (!iterator.isCarbon() && iterator.getType() == SENT) {
 					break;
 				}
 			}
@@ -577,7 +577,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 					willBeEncrypted = true;
 					break;
 				}
-				if (iterator.getRemoteMsgId() == null && iterator.getType() == SENT) {
+				if (!iterator.isCarbon() && iterator.getType() == SENT) {
 					break;
 				}
 			}