use occupantResource for sender name

This commit is contained in:
Daniel Gultsch 2023-03-27 10:41:46 +02:00
parent f13f15cc91
commit cc07f86bf4
No known key found for this signature in database
GPG key ID: F43D18AD2A0982C2
10 changed files with 224 additions and 35 deletions

View file

@ -52,6 +52,7 @@ public final class Converters {
return input == null ? null : JidCreate.fromOrThrowUnchecked(input); return input == null ? null : JidCreate.fromOrThrowUnchecked(input);
} }
// TODO do we want to return null on null input?
@TypeConverter @TypeConverter
public static Resourcepart toResourcePart(final String input) { public static Resourcepart toResourcePart(final String input) {
return Strings.isNullOrEmpty(input) return Strings.isNullOrEmpty(input)

View file

@ -198,15 +198,20 @@ public abstract class ChatDao {
"SELECT c.id,c.accountId,c.address,c.type,m.sentAt,m.senderIdentity as" "SELECT c.id,c.accountId,c.address,c.type,m.sentAt,m.senderIdentity as"
+ " sender,m.outgoing,m.latestVersion as" + " sender,m.outgoing,m.latestVersion as"
+ " version,m.toBare,m.toResource,m.fromBare,m.fromResource,(SELECT count(id) FROM" + " version,m.toBare,m.toResource,m.fromBare,m.fromResource,(SELECT count(id) FROM"
+ " message WHERE chatId=c.id) as unread,(SELECT name FROM roster WHERE" + " message WHERE chatId=c.id) as unread,(CASE WHEN c.type = 'INDIVIDUAL' THEN"
+ " roster.accountId=c.accountId AND roster.address=c.address) as" + " (SELECT name FROM roster WHERE roster.accountId=c.accountId AND"
+ " rosterName,(SELECT nick FROM nick WHERE nick.accountId=c.accountId AND" + " roster.address=c.address) ELSE NULL END) as rosterName,(CASE WHEN c.type ="
+ " nick.address=c.address) as nick,(SELECT identity.name FROM disco_item JOIN" + " 'INDIVIDUAL' THEN (SELECT nick FROM nick WHERE nick.accountId=c.accountId AND"
+ " disco_identity identity ON disco_item.discoId=identity.discoId WHERE" + " nick.address=c.address) ELSE NULL END) as nick,(CASE WHEN c.type IN('MUC') THEN"
+ " disco_item.accountId=c.accountId AND disco_item.address=c.address LIMIT 1) as" + " (SELECT name FROM roster WHERE roster.accountId=c.accountId AND"
+ " discoIdentityName,(SELECT name FROM bookmark WHERE" + " roster.address=m.senderIdentity) ELSE NULL END) as senderRosterName,(CASE WHEN"
+ " bookmark.accountId=c.accountId AND bookmark.address=c.address) as" + " c.type IN ('MUC') THEN (SELECT nick FROM nick WHERE nick.accountId=c.accountId"
+ " bookmarkName,(CASE WHEN c.type='MUC' THEN (SELECT vCardPhoto FROM presence" + " AND nick.address=m.senderIdentity) ELSE NULL END) as senderNick,(SELECT"
+ " identity.name FROM disco_item JOIN disco_identity identity ON"
+ " disco_item.discoId=identity.discoId WHERE disco_item.accountId=c.accountId AND"
+ " disco_item.address=c.address LIMIT 1) as discoIdentityName,(SELECT name FROM"
+ " bookmark WHERE bookmark.accountId=c.accountId AND bookmark.address=c.address)"
+ " as bookmarkName,(CASE WHEN c.type='MUC' THEN (SELECT vCardPhoto FROM presence"
+ " WHERE presence.accountId=c.accountId AND address=c.address AND resource='')" + " WHERE presence.accountId=c.accountId AND address=c.address AND resource='')"
+ " WHEN c.type='INDIVIDUAL' THEN (SELECT vCardPhoto FROM presence WHERE" + " WHEN c.type='INDIVIDUAL' THEN (SELECT vCardPhoto FROM presence WHERE"
+ " accountId=c.accountId AND address=c.address AND vCardPhoto NOT NULL LIMIT 1)" + " accountId=c.accountId AND address=c.address AND vCardPhoto NOT NULL LIMIT 1)"

View file

@ -3,6 +3,7 @@ package im.conversations.android.database.model;
import androidx.room.Relation; import androidx.room.Relation;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import im.conversations.android.database.KnownSender;
import im.conversations.android.database.entity.MessageContentEntity; import im.conversations.android.database.entity.MessageContentEntity;
import java.time.Instant; import java.time.Instant;
import java.util.List; import java.util.List;
@ -10,7 +11,7 @@ import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.Jid; import org.jxmpp.jid.Jid;
import org.jxmpp.jid.parts.Resourcepart; import org.jxmpp.jid.parts.Resourcepart;
public class ChatOverviewItem extends ChatInfo { public class ChatOverviewItem extends ChatInfo implements KnownSender {
public long id; public long id;
@ -24,6 +25,8 @@ public class ChatOverviewItem extends ChatInfo {
public String fromResource; public String fromResource;
public BareJid sender; public BareJid sender;
public String senderNick;
public String senderRosterName;
public long version; public long version;
@ -45,17 +48,63 @@ public class ChatOverviewItem extends ChatInfo {
return firstMessageContent == null ? null : firstMessageContent.body; return firstMessageContent == null ? null : firstMessageContent.body;
} }
public Sender getSender() { @Override
public ChatType getChatType() {
return this.type;
}
@Override
public boolean isMembersOnlyNonAnonymous() {
return this.membersOnlyNonAnonymous;
}
@Override
public BareJid getSender() {
return this.sender;
}
public Sender getMessageSender() {
if (outgoing) { if (outgoing) {
return new SenderYou(); return new SenderYou();
} else if (type == ChatType.MUC) { } else if (type == ChatType.MUC) {
if (fromResource != null) { if (isKnownSender()) {
return new SenderName(fromResource); return new SenderName(individualName());
} else { } else {
return null; if (occupantResource != null && occupantResource.length() > 0) {
return new SenderName(occupantResource.toString());
}
if (fromResource != null && fromResource.length() > 0) {
return new SenderName(fromResource.toString());
}
} }
}
return null;
}
@Override
public String individualRosterName() {
if (type == ChatType.INDIVIDUAL) {
return super.individualRosterName();
} else { } else {
return null; return this.senderRosterName;
}
}
@Override
public String individualNick() {
if (type == ChatType.INDIVIDUAL) {
return super.individualNick();
} else {
return senderNick;
}
}
@Override
public BareJid individualAddress() {
if (type == ChatType.INDIVIDUAL) {
return super.individualAddress();
} else {
return this.sender;
} }
} }
@ -88,23 +137,20 @@ public class ChatOverviewItem extends ChatInfo {
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
ChatOverviewItem that = (ChatOverviewItem) o; ChatOverviewItem that = (ChatOverviewItem) o;
return id == that.id return id == that.id
&& accountId == that.accountId
&& outgoing == that.outgoing && outgoing == that.outgoing
&& version == that.version && version == that.version
&& unread == that.unread && unread == that.unread
&& Objects.equal(address, that.address)
&& type == that.type
&& Objects.equal(sentAt, that.sentAt) && Objects.equal(sentAt, that.sentAt)
&& Objects.equal(toBare, that.toBare) && Objects.equal(toBare, that.toBare)
&& Objects.equal(toResource, that.toResource) && Objects.equal(toResource, that.toResource)
&& Objects.equal(fromBare, that.fromBare) && Objects.equal(fromBare, that.fromBare)
&& Objects.equal(fromResource, that.fromResource) && Objects.equal(fromResource, that.fromResource)
&& Objects.equal(rosterName, that.rosterName) && Objects.equal(sender, that.sender)
&& Objects.equal(nick, that.nick) && Objects.equal(senderNick, that.senderNick)
&& Objects.equal(discoIdentityName, that.discoIdentityName) && Objects.equal(senderRosterName, that.senderRosterName)
&& Objects.equal(bookmarkName, that.bookmarkName)
&& Objects.equal(vCardPhoto, that.vCardPhoto) && Objects.equal(vCardPhoto, that.vCardPhoto)
&& Objects.equal(avatar, that.avatar) && Objects.equal(avatar, that.avatar)
&& Objects.equal(occupantResource, that.occupantResource)
&& Objects.equal(contents, that.contents); && Objects.equal(contents, that.contents);
} }
@ -112,22 +158,19 @@ public class ChatOverviewItem extends ChatInfo {
public int hashCode() { public int hashCode() {
return Objects.hashCode( return Objects.hashCode(
id, id,
accountId,
address,
type,
sentAt, sentAt,
outgoing, outgoing,
toBare, toBare,
toResource, toResource,
fromBare, fromBare,
fromResource, fromResource,
sender,
senderNick,
senderRosterName,
version, version,
rosterName,
nick,
discoIdentityName,
bookmarkName,
vCardPhoto, vCardPhoto,
avatar, avatar,
occupantResource,
unread, unread,
contents); contents);
} }

View file

@ -1,6 +1,7 @@
package im.conversations.android.database.model; package im.conversations.android.database.model;
import androidx.room.Relation; import androidx.room.Relation;
import com.google.common.base.Objects;
import im.conversations.android.database.entity.MessageContentEntity; import im.conversations.android.database.entity.MessageContentEntity;
import java.time.Instant; import java.time.Instant;
import java.util.List; import java.util.List;
@ -20,4 +21,22 @@ public class MessageEmbedded {
parentColumn = "latestVersion", parentColumn = "latestVersion",
entityColumn = "messageVersionId") entityColumn = "messageVersionId")
public List<MessageContent> contents; public List<MessageContent> contents;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MessageEmbedded that = (MessageEmbedded) o;
return id == that.id
&& Objects.equal(fromBare, that.fromBare)
&& Objects.equal(fromResource, that.fromResource)
&& Objects.equal(sentAt, that.sentAt)
&& Objects.equal(latestVersion, that.latestVersion)
&& Objects.equal(contents, that.contents);
}
@Override
public int hashCode() {
return Objects.hashCode(id, fromBare, fromResource, sentAt, latestVersion, contents);
}
} }

View file

@ -1,5 +1,6 @@
package im.conversations.android.database.model; package im.conversations.android.database.model;
import com.google.common.base.Objects;
import org.jxmpp.jid.Jid; import org.jxmpp.jid.Jid;
public class MessageReaction { public class MessageReaction {
@ -17,4 +18,20 @@ public class MessageReaction {
this.occupantId = occupantId; this.occupantId = occupantId;
this.reaction = reaction; this.reaction = reaction;
} }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MessageReaction that = (MessageReaction) o;
return Objects.equal(reactionBy, that.reactionBy)
&& Objects.equal(reactionByResource, that.reactionByResource)
&& Objects.equal(occupantId, that.occupantId)
&& Objects.equal(reaction, that.reaction);
}
@Override
public int hashCode() {
return Objects.hashCode(reactionBy, reactionByResource, occupantId, reaction);
}
} }

View file

@ -1,5 +1,6 @@
package im.conversations.android.database.model; package im.conversations.android.database.model;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import im.conversations.android.transformer.MessageTransformation; import im.conversations.android.transformer.MessageTransformation;
import im.conversations.android.xmpp.model.error.Condition; import im.conversations.android.xmpp.model.error.Condition;
@ -64,4 +65,21 @@ public class MessageState {
null, null,
null); null);
} }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MessageState that = (MessageState) o;
return Objects.equal(fromBare, that.fromBare)
&& Objects.equal(fromResource, that.fromResource)
&& type == that.type
&& Objects.equal(errorCondition, that.errorCondition)
&& Objects.equal(errorText, that.errorText);
}
@Override
public int hashCode() {
return Objects.hashCode(fromBare, fromResource, type, errorCondition, errorText);
}
} }

View file

@ -1,6 +1,7 @@
package im.conversations.android.database.model; package im.conversations.android.database.model;
import androidx.room.Relation; import androidx.room.Relation;
import com.google.common.base.Objects;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -48,7 +49,7 @@ public class MessageWithContentReactions implements IndividualName, KnownSender
public String senderNick; public String senderNick;
public String occupantVcardPhoto; public String occupantVcardPhoto;
public String occupantResource; public Resourcepart occupantResource;
public Modification modification; public Modification modification;
public long version; public long version;
@ -101,9 +102,13 @@ public class MessageWithContentReactions implements IndividualName, KnownSender
if (isKnownSender()) { if (isKnownSender()) {
return new AddressWithName(individualAddress(), individualName()); return new AddressWithName(individualAddress(), individualName());
} else { } else {
final Jid address = JidCreate.fullFrom(fromBare, fromResource); final Jid address;
final String name = fromResource.toString(); if (occupantResource != null && occupantResource.length() != 0) {
return new AddressWithName(address, name); address = JidCreate.fullFrom(fromBare, occupantResource);
} else {
address = JidCreate.fullFrom(fromBare, fromResource);
}
return new AddressWithName(address, address.getResourceOrEmpty().toString());
} }
} }
@ -159,7 +164,8 @@ public class MessageWithContentReactions implements IndividualName, KnownSender
} }
public String getSenderName() { public String getSenderName() {
return this.fromResource == null ? null : fromResource.toString(); final var addressWithName = getAddressWithName();
return addressWithName.name;
} }
public boolean isGroupChat() { public boolean isGroupChat() {
@ -170,6 +176,72 @@ public class MessageWithContentReactions implements IndividualName, KnownSender
return new EncryptionTuple(this.encryption, this.trust); return new EncryptionTuple(this.encryption, this.trust);
} }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MessageWithContentReactions that = (MessageWithContentReactions) o;
return accountId == that.accountId
&& id == that.id
&& membersOnlyNonAnonymous == that.membersOnlyNonAnonymous
&& outgoing == that.outgoing
&& version == that.version
&& chatType == that.chatType
&& Objects.equal(sentAt, that.sentAt)
&& Objects.equal(toBare, that.toBare)
&& Objects.equal(toResource, that.toResource)
&& Objects.equal(fromBare, that.fromBare)
&& Objects.equal(fromResource, that.fromResource)
&& Objects.equal(sender, that.sender)
&& Objects.equal(senderVcardPhoto, that.senderVcardPhoto)
&& Objects.equal(senderAvatar, that.senderAvatar)
&& Objects.equal(senderRosterName, that.senderRosterName)
&& Objects.equal(senderNick, that.senderNick)
&& Objects.equal(occupantVcardPhoto, that.occupantVcardPhoto)
&& Objects.equal(occupantResource, that.occupantResource)
&& modification == that.modification
&& Objects.equal(inReplyToMessageEntityId, that.inReplyToMessageEntityId)
&& encryption == that.encryption
&& Objects.equal(identityKey, that.identityKey)
&& trust == that.trust
&& Objects.equal(inReplyTo, that.inReplyTo)
&& Objects.equal(contents, that.contents)
&& Objects.equal(reactions, that.reactions)
&& Objects.equal(states, that.states);
}
@Override
public int hashCode() {
return Objects.hashCode(
accountId,
id,
chatType,
membersOnlyNonAnonymous,
sentAt,
outgoing,
toBare,
toResource,
fromBare,
fromResource,
sender,
senderVcardPhoto,
senderAvatar,
senderRosterName,
senderNick,
occupantVcardPhoto,
occupantResource,
modification,
version,
inReplyToMessageEntityId,
encryption,
identityKey,
trust,
inReplyTo,
contents,
reactions,
states);
}
public static class EncryptionTuple { public static class EncryptionTuple {
public final Encryption encryption; public final Encryption encryption;
public final Trust trust; public final Trust trust;

View file

@ -12,11 +12,15 @@ import im.conversations.android.R;
import im.conversations.android.database.model.MessageWithContentReactions; import im.conversations.android.database.model.MessageWithContentReactions;
import im.conversations.android.databinding.ItemMessageReceivedBinding; import im.conversations.android.databinding.ItemMessageReceivedBinding;
import im.conversations.android.ui.AvatarFetcher; import im.conversations.android.ui.AvatarFetcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MessageAdapter public class MessageAdapter
extends PagingDataAdapter< extends PagingDataAdapter<
MessageWithContentReactions, MessageAdapter.AbstractMessageViewHolder> { MessageWithContentReactions, MessageAdapter.AbstractMessageViewHolder> {
private static final Logger LOGGER = LoggerFactory.getLogger(MessageAdapter.class);
public MessageAdapter( public MessageAdapter(
@NonNull DiffUtil.ItemCallback<MessageWithContentReactions> diffCallback) { @NonNull DiffUtil.ItemCallback<MessageWithContentReactions> diffCallback) {
super(diffCallback); super(diffCallback);
@ -41,6 +45,7 @@ public class MessageAdapter
if (message == null) { if (message == null) {
holder.setMessage(null); holder.setMessage(null);
} }
LOGGER.info("onBindViewHolder({})", message == null ? null : message.id);
holder.setMessage(message); holder.setMessage(message);
if (holder instanceof MessageReceivedViewHolder messageReceivedViewHolder) { if (holder instanceof MessageReceivedViewHolder messageReceivedViewHolder) {
final var addressWithName = message == null ? null : message.getAddressWithName(); final var addressWithName = message == null ? null : message.getAddressWithName();

View file

@ -3,8 +3,13 @@ package im.conversations.android.ui.adapter;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.DiffUtil;
import im.conversations.android.database.model.MessageWithContentReactions; import im.conversations.android.database.model.MessageWithContentReactions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MessageComparator extends DiffUtil.ItemCallback<MessageWithContentReactions> { public class MessageComparator extends DiffUtil.ItemCallback<MessageWithContentReactions> {
private static final Logger LOGGER = LoggerFactory.getLogger(MessageComparator.class);
@Override @Override
public boolean areItemsTheSame( public boolean areItemsTheSame(
@NonNull MessageWithContentReactions oldItem, @NonNull MessageWithContentReactions oldItem,
@ -16,6 +21,10 @@ public class MessageComparator extends DiffUtil.ItemCallback<MessageWithContentR
public boolean areContentsTheSame( public boolean areContentsTheSame(
@NonNull MessageWithContentReactions oldItem, @NonNull MessageWithContentReactions oldItem,
@NonNull MessageWithContentReactions newItem) { @NonNull MessageWithContentReactions newItem) {
final var equals = oldItem.equals(newItem);
if (!equals) {
LOGGER.info("Message {} got modified", oldItem.id);
}
return false; return false;
} }
} }

View file

@ -43,7 +43,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="4sp" android:layout_marginEnd="4sp"
android:maxLines="1" android:maxLines="1"
android:text="@{chatOverviewItem.sender}" android:text="@{chatOverviewItem.messageSender}"
android:textAppearance="?textAppearanceBodyMedium" android:textAppearance="?textAppearanceBodyMedium"
android:textColor="?colorTertiary" android:textColor="?colorTertiary"
android:visibility="visible" android:visibility="visible"