support reaction arriving before message

This commit is contained in:
Daniel Gultsch 2023-02-12 09:43:20 +01:00
parent fbb900d4ad
commit 4c09b20aa4
No known key found for this signature in database
GPG key ID: F43D18AD2A0982C2
4 changed files with 104 additions and 6 deletions

View file

@ -4,6 +4,7 @@ import android.content.Context;
import androidx.room.Room; import androidx.room.Room;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.Iterables;
import eu.siacs.conversations.xmpp.Jid; import eu.siacs.conversations.xmpp.Jid;
import im.conversations.android.IDs; import im.conversations.android.IDs;
import im.conversations.android.database.ConversationsDatabase; import im.conversations.android.database.ConversationsDatabase;
@ -16,6 +17,7 @@ import im.conversations.android.xmpp.model.reactions.Reactions;
import im.conversations.android.xmpp.model.stanza.Message; import im.conversations.android.xmpp.model.stanza.Message;
import java.time.Instant; import java.time.Instant;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -26,13 +28,15 @@ public class TransformationTest {
private static final Jid ACCOUNT = Jid.of("user@example.com"); private static final Jid ACCOUNT = Jid.of("user@example.com");
private static final Jid REMOTE = Jid.of("juliet@example.com"); private static final Jid REMOTE = Jid.of("juliet@example.com");
private static final String GREETING = "Hi Juliet. How are you?";
private ConversationsDatabase database;
private Transformer transformer; private Transformer transformer;
@Before @Before
public void setupTransformer() throws ExecutionException, InterruptedException { public void setupTransformer() throws ExecutionException, InterruptedException {
Context context = ApplicationProvider.getApplicationContext(); Context context = ApplicationProvider.getApplicationContext();
final var database = this.database = Room.inMemoryDatabaseBuilder(context, ConversationsDatabase.class).build();
Room.inMemoryDatabaseBuilder(context, ConversationsDatabase.class).build();
final var account = new AccountEntity(); final var account = new AccountEntity();
account.address = ACCOUNT; account.address = ACCOUNT;
account.enabled = true; account.enabled = true;
@ -60,8 +64,17 @@ public class TransformationTest {
originalMessage.setTo(REMOTE); originalMessage.setTo(REMOTE);
originalMessage.setFrom(ACCOUNT.withResource("junit")); originalMessage.setFrom(ACCOUNT.withResource("junit"));
final var body = originalMessage.addExtension(new Body()); final var body = originalMessage.addExtension(new Body());
body.setContent("Hi Juliet. How are you?"); body.setContent(GREETING);
this.transformer.transform( this.transformer.transform(
Transformation.of(originalMessage, Instant.now(), REMOTE, "stanza-a", null)); Transformation.of(originalMessage, Instant.now(), REMOTE, "stanza-a", null));
final var messages = database.messageDao().getMessages(1L);
Assert.assertEquals(1, messages.size());
final var message = Iterables.getOnlyElement(messages);
final var onlyContent = Iterables.getOnlyElement(message.contents);
Assert.assertEquals(GREETING, onlyContent.body);
final var onlyReaction = Iterables.getOnlyElement(message.reactions);
Assert.assertEquals("Y", onlyReaction.reaction);
Assert.assertEquals(REMOTE, onlyReaction.reactionBy);
} }
} }

View file

@ -5,6 +5,7 @@ import androidx.room.Dao;
import androidx.room.Insert; import androidx.room.Insert;
import androidx.room.Query; import androidx.room.Query;
import androidx.room.Transaction; import androidx.room.Transaction;
import androidx.room.Update;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.Collections2; import com.google.common.collect.Collections2;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@ -19,6 +20,7 @@ import im.conversations.android.database.model.ChatIdentifier;
import im.conversations.android.database.model.MessageContent; import im.conversations.android.database.model.MessageContent;
import im.conversations.android.database.model.MessageIdentifier; import im.conversations.android.database.model.MessageIdentifier;
import im.conversations.android.database.model.MessageState; import im.conversations.android.database.model.MessageState;
import im.conversations.android.database.model.MessageWithContentReactions;
import im.conversations.android.database.model.Modification; import im.conversations.android.database.model.Modification;
import im.conversations.android.transformer.Transformation; import im.conversations.android.transformer.Transformation;
import im.conversations.android.xmpp.model.reactions.Reactions; import im.conversations.android.xmpp.model.reactions.Reactions;
@ -80,9 +82,23 @@ public abstract class MessageDao {
"Found stub for stanzaId '{}' and messageId '{}'", "Found stub for stanzaId '{}' and messageId '{}'",
transformation.stanzaId, transformation.stanzaId,
transformation.messageId); transformation.messageId);
// TODO create version final long messageVersionId =
// TODO fill up information insert(
return messageIdentifier; MessageVersionEntity.of(
messageIdentifier.id,
Modification.ORIGINAl,
transformation));
final MessageEntity updatedEntity =
MessageEntity.of(chatIdentifier.id, transformation);
updatedEntity.id = messageIdentifier.id;
updatedEntity.latestVersion = messageVersionId;
update(updatedEntity);
return new MessageIdentifier(
updatedEntity.id,
transformation.stanzaId,
transformation.messageId,
transformation.fromBare(),
messageVersionId);
} else { } else {
throw new IllegalStateException( throw new IllegalStateException(
String.format( String.format(
@ -201,6 +217,9 @@ public abstract class MessageDao {
@Insert @Insert
protected abstract long insert(MessageEntity messageEntity); protected abstract long insert(MessageEntity messageEntity);
@Update
protected abstract void update(final MessageEntity messageEntity);
@Insert @Insert
protected abstract long insert(MessageVersionEntity messageVersionEntity); protected abstract long insert(MessageVersionEntity messageVersionEntity);
@ -293,4 +312,13 @@ public abstract class MessageDao {
reactions.getReactions(), reactions.getReactions(),
r -> MessageReactionEntity.of(messageIdentifier.id, r, transformation))); r -> MessageReactionEntity.of(messageIdentifier.id, r, transformation)));
} }
@Transaction
@Query(
"SELECT message.id as"
+ " id,sentAt,outgoing,toBare,toResource,fromBare,fromResource,modification,latestVersion"
+ " as version FROM message JOIN message_version ON"
+ " message.latestVersion=message_version.id WHERE message.chatId=:chatId AND"
+ " latestVersion IS NOT NULL ORDER BY message.receivedAt")
public abstract List<MessageWithContentReactions> getMessages(long chatId);
} }

View file

@ -0,0 +1,20 @@
package im.conversations.android.database.model;
import eu.siacs.conversations.xmpp.Jid;
public class MessageReaction {
public final Jid reactionBy;
public final String reactionByResource;
public final String occupantId;
public final String reaction;
public MessageReaction(
Jid reactionBy, String reactionByResource, String occupantId, String reaction) {
this.reactionBy = reactionBy;
this.reactionByResource = reactionByResource;
this.occupantId = occupantId;
this.reaction = reaction;
}
}

View file

@ -0,0 +1,37 @@
package im.conversations.android.database.model;
import androidx.room.Relation;
import eu.siacs.conversations.xmpp.Jid;
import im.conversations.android.database.entity.MessageContentEntity;
import im.conversations.android.database.entity.MessageReactionEntity;
import java.time.Instant;
import java.util.List;
public class MessageWithContentReactions {
public long id;
public Instant sentAt;
public boolean outgoing;
public Jid toBare;
public String toResource;
public Jid fromBare;
public String fromResource;
public Modification modification;
public long version;
@Relation(
entity = MessageContentEntity.class,
parentColumn = "version",
entityColumn = "messageVersionId")
public List<MessageContent> contents;
@Relation(
entity = MessageReactionEntity.class,
parentColumn = "id",
entityColumn = "messageEntityId")
public List<MessageReaction> reactions;
}