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 a new issue