This commit is contained in:
nielsandriesse 2020-05-12 11:26:44 +10:00
parent 8e53383ab9
commit b9d8d100d9
6 changed files with 35 additions and 32 deletions

View File

@ -83,11 +83,13 @@ public class TypingStatusSender {
private void sendTyping(long threadId, boolean typingStarted) { private void sendTyping(long threadId, boolean typingStarted) {
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context); ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
Recipient recipient = threadDatabase.getRecipientForThreadId(threadId); Recipient recipient = threadDatabase.getRecipientForThreadId(threadId);
// Loki - Check whether we want to send a typing indicator to this user
if (!SessionMetaProtocol.shouldSendTypingIndicator(recipient, context)) { return; } if (!SessionMetaProtocol.shouldSendTypingIndicator(recipient, context)) { return; }
// Loki - Take into account multi device
Set<String> linkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(recipient.getAddress().serialize()); Set<String> linkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(recipient.getAddress().serialize());
for (String device : linkedDevices) { for (String device : linkedDevices) {
Recipient deviceAsRecipient = Recipient.from(context, Address.fromSerialized(device), false); 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)); ApplicationContext.getInstance(context).getJobManager().add(new TypingSendJob(deviceThreadID, typingStarted));
} }
} }

View File

@ -89,7 +89,7 @@ public class SendReadReceiptJob extends BaseJob implements InjectableType {
SignalServiceAddress remoteAddress = new SignalServiceAddress(address); SignalServiceAddress remoteAddress = new SignalServiceAddress(address);
SignalServiceReceiptMessage receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.READ, messageIds, timestamp); 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)), UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.fromSerialized(address), false)),
receiptMessage); receiptMessage);
} }

View File

@ -10,7 +10,6 @@ import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.jobmanager.Data; import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.GroupUtil; import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences; 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 org.whispersystems.signalservice.api.push.SignalServiceAddress;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.inject.Inject; 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."); throw new IllegalStateException("Tried to send a typing indicator to a non-existent thread.");
} }
List<Recipient> recipients = Collections.singletonList(recipient); Set<Recipient> recipients = new HashSet<>(Collections.singletonList(recipient));
Optional<byte[]> groupId = Optional.absent(); Optional<byte[]> groupId = Optional.absent();
if (recipient.isGroupRecipient()) { 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())); groupId = Optional.of(GroupUtil.getDecodedId(recipient.getAddress().toGroupString()));
} }
@ -97,9 +98,7 @@ public class TypingSendJob extends BaseJob implements InjectableType {
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(recipients).map(r -> UnidentifiedAccessUtil.getAccessFor(context, r)).toList(); List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(recipients).map(r -> UnidentifiedAccessUtil.getAccessFor(context, r)).toList();
SignalServiceTypingMessage typingMessage = new SignalServiceTypingMessage(typing ? Action.STARTED : Action.STOPPED, System.currentTimeMillis(), groupId); 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 @Override

View File

@ -4,34 +4,38 @@ import android.content.Context
import org.thoughtcrime.securesms.database.Address import org.thoughtcrime.securesms.database.Address
import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.Recipient
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
object SessionMetaProtocol { object SessionMetaProtocol {
/**
* Should be invoked for the recipient's master device.
*/
@JvmStatic @JvmStatic
fun canUserReplyToNotification(recipient: Recipient, context: Context): Boolean { fun canUserReplyToNotification(recipient: Recipient, context: Context): Boolean {
val isGroup = recipient.isGroupRecipient val isGroup = recipient.isGroupRecipient
if (isGroup) { return !recipient.address.isRSSFeed } 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) val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient)
return DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS 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 @JvmStatic
fun shouldSendTypingIndicator(recipient: Recipient, context: Context): Boolean { fun shouldSendTypingIndicator(recipient: Recipient, context: Context): Boolean {
if (recipient.isGroupRecipient) { return false } if (recipient.isGroupRecipient) { return false }
val recipient = Recipient.from(context, Address.fromSerialized(recipient.address.serialize()),false)
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient) val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient)
return DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS return DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS
} }

View File

@ -6,6 +6,6 @@ object SyncMessagesProtocol {
@JvmStatic @JvmStatic
fun shouldSyncReadReceipt(address: Address): Boolean { fun shouldSyncReadReceipt(address: Address): Boolean {
return !address.isOpenGroup return !address.isGroup
} }
} }

View File

@ -20,11 +20,9 @@ import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
import org.thoughtcrime.securesms.jobs.MultiDeviceReadUpdateJob; import org.thoughtcrime.securesms.jobs.MultiDeviceReadUpdateJob;
import org.thoughtcrime.securesms.jobs.SendReadReceiptJob; import org.thoughtcrime.securesms.jobs.SendReadReceiptJob;
import org.thoughtcrime.securesms.logging.Log; 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.SessionMetaProtocol;
import org.thoughtcrime.securesms.loki.protocol.SyncMessagesProtocol; import org.thoughtcrime.securesms.loki.protocol.SyncMessagesProtocol;
import org.thoughtcrime.securesms.service.ExpiringMessageManager; import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol; import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol;
import java.util.LinkedList; import java.util.LinkedList;
@ -32,8 +30,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import kotlin.Unit;
public class MarkReadReceiver extends BroadcastReceiver { public class MarkReadReceiver extends BroadcastReceiver {
private static final String TAG = MarkReadReceiver.class.getSimpleName(); private static final String TAG = MarkReadReceiver.class.getSimpleName();
@ -81,9 +77,8 @@ public class MarkReadReceiver extends BroadcastReceiver {
for (MarkedMessageInfo messageInfo : markedReadMessages) { for (MarkedMessageInfo messageInfo : markedReadMessages) {
scheduleDeletion(context, messageInfo.getExpirationInfo()); scheduleDeletion(context, messageInfo.getExpirationInfo());
if (SyncMessagesProtocol.shouldSyncReadReceipt(messageInfo.getSyncMessageId().getAddress())) { if (!SyncMessagesProtocol.shouldSyncReadReceipt(messageInfo.getSyncMessageId().getAddress())) { continue; }
syncMessageIds.add(messageInfo.getSyncMessageId()); syncMessageIds.add(messageInfo.getSyncMessageId());
}
} }
ApplicationContext.getInstance(context) ApplicationContext.getInstance(context)
@ -96,12 +91,15 @@ public class MarkReadReceiver extends BroadcastReceiver {
for (Address address : addressMap.keySet()) { for (Address address : addressMap.keySet()) {
List<Long> timestamps = Stream.of(addressMap.get(address)).map(SyncMessageId::getTimetamp).toList(); List<Long> 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<String> linkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(address.serialize()); Set<String> linkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(address.serialize());
for (String device : linkedDevices) { for (String device : linkedDevices) {
if (!SessionMetaProtocol.shouldSendReadReceipt(device, context)) { continue; } Address deviceAsAddress = Address.fromExternal(context, device);
ApplicationContext.getInstance(context) ApplicationContext.getInstance(context)
.getJobManager() .getJobManager()
.add(new SendReadReceiptJob(address, timestamps)); .add(new SendReadReceiptJob(deviceAsAddress, timestamps));
} }
} }
} }