diff --git a/src/org/thoughtcrime/securesms/components/TypingStatusSender.java b/src/org/thoughtcrime/securesms/components/TypingStatusSender.java index 3659abb71e..dc510073fc 100644 --- a/src/org/thoughtcrime/securesms/components/TypingStatusSender.java +++ b/src/org/thoughtcrime/securesms/components/TypingStatusSender.java @@ -83,11 +83,13 @@ public class TypingStatusSender { private void sendTyping(long threadId, boolean typingStarted) { ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context); Recipient recipient = threadDatabase.getRecipientForThreadId(threadId); + // Loki - Check whether we want to send a typing indicator to this user if (!SessionMetaProtocol.shouldSendTypingIndicator(recipient, context)) { return; } + // Loki - Take into account multi device Set linkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(recipient.getAddress().serialize()); for (String device : linkedDevices) { Recipient deviceAsRecipient = Recipient.from(context, Address.fromSerialized(device), false); - long deviceThreadID = threadDatabase.getThreadIdFor(deviceAsRecipient) + long deviceThreadID = threadDatabase.getThreadIdFor(deviceAsRecipient); ApplicationContext.getInstance(context).getJobManager().add(new TypingSendJob(deviceThreadID, typingStarted)); } } diff --git a/src/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java b/src/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java index 85bbe65d4c..da08f5aa1f 100644 --- a/src/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java +++ b/src/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java @@ -89,7 +89,7 @@ public class SendReadReceiptJob extends BaseJob implements InjectableType { SignalServiceAddress remoteAddress = new SignalServiceAddress(address); SignalServiceReceiptMessage receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.READ, messageIds, timestamp); - messageSender.sendReceipt(0, remoteAddress, // The message ID doesn't matter + messageSender.sendReceipt(remoteAddress, UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.fromSerialized(address), false)), receiptMessage); } diff --git a/src/org/thoughtcrime/securesms/jobs/TypingSendJob.java b/src/org/thoughtcrime/securesms/jobs/TypingSendJob.java index dc5aba1d53..dd8260080e 100644 --- a/src/org/thoughtcrime/securesms/jobs/TypingSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/TypingSendJob.java @@ -10,7 +10,6 @@ import org.thoughtcrime.securesms.dependencies.InjectableType; import org.thoughtcrime.securesms.jobmanager.Data; import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.logging.Log; -import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.GroupUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; @@ -22,7 +21,9 @@ import org.whispersystems.signalservice.api.messages.SignalServiceTypingMessage. import org.whispersystems.signalservice.api.push.SignalServiceAddress; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.TimeUnit; import javax.inject.Inject; @@ -85,11 +86,11 @@ public class TypingSendJob extends BaseJob implements InjectableType { throw new IllegalStateException("Tried to send a typing indicator to a non-existent thread."); } - List recipients = Collections.singletonList(recipient); - Optional groupId = Optional.absent(); + Set recipients = new HashSet<>(Collections.singletonList(recipient)); + Optional groupId = Optional.absent(); if (recipient.isGroupRecipient()) { - recipients = DatabaseFactory.getGroupDatabase(context).getGroupMembers(recipient.getAddress().toGroupString(), false); + recipients = new HashSet<>(DatabaseFactory.getGroupDatabase(context).getGroupMembers(recipient.getAddress().toGroupString(), false)); groupId = Optional.of(GroupUtil.getDecodedId(recipient.getAddress().toGroupString())); } @@ -97,9 +98,7 @@ public class TypingSendJob extends BaseJob implements InjectableType { List> unidentifiedAccess = Stream.of(recipients).map(r -> UnidentifiedAccessUtil.getAccessFor(context, r)).toList(); SignalServiceTypingMessage typingMessage = new SignalServiceTypingMessage(typing ? Action.STARTED : Action.STOPPED, System.currentTimeMillis(), groupId); - if (SessionMetaProtocol.shouldSendTypingIndicator(recipient, context)) { - messageSender.sendTyping(addresses, unidentifiedAccess, typingMessage); - } + messageSender.sendTyping(addresses, unidentifiedAccess, typingMessage); } @Override diff --git a/src/org/thoughtcrime/securesms/loki/protocol/SessionMetaProtocol.kt b/src/org/thoughtcrime/securesms/loki/protocol/SessionMetaProtocol.kt index c69d7bbe04..f667321bdc 100644 --- a/src/org/thoughtcrime/securesms/loki/protocol/SessionMetaProtocol.kt +++ b/src/org/thoughtcrime/securesms/loki/protocol/SessionMetaProtocol.kt @@ -4,34 +4,38 @@ import android.content.Context import org.thoughtcrime.securesms.database.Address import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.recipients.Recipient -import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus object SessionMetaProtocol { + /** + * Should be invoked for the recipient's master device. + */ @JvmStatic fun canUserReplyToNotification(recipient: Recipient, context: Context): Boolean { val isGroup = recipient.isGroupRecipient if (isGroup) { return !recipient.address.isRSSFeed } - val linkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(recipient.address.serialize()) - return linkedDevices.any { device -> - val recipient = Recipient.from(context, Address.fromSerialized(device), false) - val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient) - DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS - } - } - - @JvmStatic - fun shouldSendReadReceipt(publicKey: String, context: Context): Boolean { - val recipient = Recipient.from(context, Address.fromSerialized(publicKey),false) val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient) return DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS } + /** + * Should be invoked for the recipient's master device. + */ + @JvmStatic + fun shouldSendReadReceipt(address: Address, context: Context): Boolean { + if (address.isGroup) { return false } + val recipient = Recipient.from(context, address,false) + val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient) + return DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS + } + + /** + * Should be invoked for the recipient's master device. + */ @JvmStatic fun shouldSendTypingIndicator(recipient: Recipient, context: Context): Boolean { if (recipient.isGroupRecipient) { return false } - val recipient = Recipient.from(context, Address.fromSerialized(recipient.address.serialize()),false) val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient) return DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS } diff --git a/src/org/thoughtcrime/securesms/loki/protocol/SyncMessagesProtocol.kt b/src/org/thoughtcrime/securesms/loki/protocol/SyncMessagesProtocol.kt index f8c4db83a7..4ab38a927f 100644 --- a/src/org/thoughtcrime/securesms/loki/protocol/SyncMessagesProtocol.kt +++ b/src/org/thoughtcrime/securesms/loki/protocol/SyncMessagesProtocol.kt @@ -6,6 +6,6 @@ object SyncMessagesProtocol { @JvmStatic fun shouldSyncReadReceipt(address: Address): Boolean { - return !address.isOpenGroup + return !address.isGroup } } \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java b/src/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java index f917e85d13..5ee1a0c432 100644 --- a/src/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java +++ b/src/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java @@ -20,11 +20,9 @@ import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId; import org.thoughtcrime.securesms.jobs.MultiDeviceReadUpdateJob; import org.thoughtcrime.securesms.jobs.SendReadReceiptJob; import org.thoughtcrime.securesms.logging.Log; -import org.thoughtcrime.securesms.loki.MultiDeviceUtilities; import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol; import org.thoughtcrime.securesms.loki.protocol.SyncMessagesProtocol; import org.thoughtcrime.securesms.service.ExpiringMessageManager; -import org.thoughtcrime.securesms.util.Util; import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol; import java.util.LinkedList; @@ -32,8 +30,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import kotlin.Unit; - public class MarkReadReceiver extends BroadcastReceiver { private static final String TAG = MarkReadReceiver.class.getSimpleName(); @@ -81,9 +77,8 @@ public class MarkReadReceiver extends BroadcastReceiver { for (MarkedMessageInfo messageInfo : markedReadMessages) { scheduleDeletion(context, messageInfo.getExpirationInfo()); - if (SyncMessagesProtocol.shouldSyncReadReceipt(messageInfo.getSyncMessageId().getAddress())) { - syncMessageIds.add(messageInfo.getSyncMessageId()); - } + if (!SyncMessagesProtocol.shouldSyncReadReceipt(messageInfo.getSyncMessageId().getAddress())) { continue; } + syncMessageIds.add(messageInfo.getSyncMessageId()); } ApplicationContext.getInstance(context) @@ -96,12 +91,15 @@ public class MarkReadReceiver extends BroadcastReceiver { for (Address address : addressMap.keySet()) { List timestamps = Stream.of(addressMap.get(address)).map(SyncMessageId::getTimetamp).toList(); + // Loki - Check whether we want to send a read receipt to this user + if (!SessionMetaProtocol.shouldSendReadReceipt(address, context)) { continue; } + // Loki - Take into account multi device Set linkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(address.serialize()); for (String device : linkedDevices) { - if (!SessionMetaProtocol.shouldSendReadReceipt(device, context)) { continue; } + Address deviceAsAddress = Address.fromExternal(context, device); ApplicationContext.getInstance(context) .getJobManager() - .add(new SendReadReceiptJob(address, timestamps)); + .add(new SendReadReceiptJob(deviceAsAddress, timestamps)); } } }