diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java index 3cac1101ae..31114f6b80 100644 --- a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java @@ -2200,7 +2200,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity inputMethodManager.showSoftInput(inputPanel.composeText, 0); } boolean hasPendingFriendRequest = !recipient.isGroupRecipient() && hasPendingFriendRequestWithAnyLinkedDevice(); - boolean isFriendsWithAnyLinkedDevices = isFriendsWithAnyLinkedDevice(); + boolean isFriendsWithAnyLinkedDevices = MultiDeviceUtilitiesKt.isFriendsWithAnyLinkedDevice(this, recipient); boolean shouldEnableInput = isFriendsWithAnyLinkedDevices || !hasPendingFriendRequest; updateToggleButtonState(); inputPanel.setEnabled(shouldEnableInput); @@ -3032,33 +3032,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity updateInputPanel(); } - public boolean isFriendsWithAnyLinkedDevice() { - if (recipient.isGroupRecipient()) return true; - SettableFuture future = new SettableFuture<>(); - LokiStorageAPI storageAPI = LokiStorageAPI.Companion.getShared(); - - MultiDeviceUtilitiesKt.getAllDeviceFriendRequestStatus(this, recipient.getAddress().serialize(), storageAPI).success(map -> { - for (LokiThreadFriendRequestStatus status : map.values()) { - if (status == LokiThreadFriendRequestStatus.FRIENDS) { - future.set(true); - break; - } - } - - if (!future.isDone()) { future.set(false); } - return Unit.INSTANCE; - }).fail(e -> { - future.set(false); - return Unit.INSTANCE; - }); - - try { - return future.get(); - } catch (Exception e) { - return false; - } - } - public boolean hasPendingFriendRequestWithAnyLinkedDevice() { if (recipient.isGroupRecipient()) return false; SettableFuture future = new SettableFuture<>(); diff --git a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java index aaa222bec4..4fa07ac425 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java @@ -779,6 +779,11 @@ public class PushDecryptJob extends BaseJob implements InjectableType { return; } + // Don't insert friend request if we're already friends with a one of the users other device + if (message.isFriendRequest() && MultiDeviceUtilitiesKt.isFriendsWithAnyLinkedDevice(context, primaryDeviceRecipient)) { + return; + } + Optional insertResult; try { @@ -956,6 +961,11 @@ public class PushDecryptJob extends BaseJob implements InjectableType { // Ignore the message if the body is empty if (textMessage.getMessageBody().length() == 0) { return; } + // Don't insert friend request if we're already friends with a one of the users other device + if (message.isFriendRequest() && MultiDeviceUtilitiesKt.isFriendsWithAnyLinkedDevice(context, primaryDeviceRecipient)) { + return; + } + // Insert the message into the database Optional insertResult = database.insertMessageInbox(textMessage); @@ -1014,13 +1024,13 @@ public class PushDecryptJob extends BaseJob implements InjectableType { private void handlePairingMessage(@NonNull PairingAuthorisation authorisation, @NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content) { String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context); if (authorisation.getType() == PairingAuthorisation.Type.REQUEST) { - handlePairingRequestMessage(authorisation, envelope); + handlePairingRequestMessage(authorisation); } else if (authorisation.getSecondaryDevicePublicKey().equals(userHexEncodedPublicKey)) { handlePairingAuthorisationMessage(authorisation, envelope, content); } } - private void handlePairingRequestMessage(@NonNull PairingAuthorisation authorisation, @NonNull SignalServiceEnvelope envelope) { + private void handlePairingRequestMessage(@NonNull PairingAuthorisation authorisation) { boolean isValid = isValidPairingMessage(authorisation); DeviceLinkingSession linkingSession = DeviceLinkingSession.Companion.getShared(); if (isValid && linkingSession.isListeningForLinkingRequests()) { @@ -1093,6 +1103,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType { // it must be a friend request accepted message. Declining a friend request doesn't send a message. lokiThreadDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS); // Update the last message if needed + // TODO: Fix this logic to update the last friend request message SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context); LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context); int messageCount = smsDatabase.getMessageCountForThread(threadID); @@ -1137,6 +1148,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType { // `REQUEST_SENT`. lokiThreadDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS); // Since messages are forwarded to the primary device thread, we need to update it there + // TODO: Fix this logic to update the last friend request message long messageID = smsMessageDatabase.getIDForMessageAtIndex(primaryDeviceThreadID, messageCount - 2); // The message before the one that was just received lokiMessageDatabase.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED); // Accept the friend request diff --git a/src/org/thoughtcrime/securesms/loki/FriendRequestHandler.kt b/src/org/thoughtcrime/securesms/loki/FriendRequestHandler.kt new file mode 100644 index 0000000000..d68bc09bdd --- /dev/null +++ b/src/org/thoughtcrime/securesms/loki/FriendRequestHandler.kt @@ -0,0 +1,51 @@ +package org.thoughtcrime.securesms.loki + +import android.content.Context +import nl.komponents.kovenant.Promise +import nl.komponents.kovenant.ui.alwaysUi +import nl.komponents.kovenant.ui.successUi +import org.thoughtcrime.securesms.database.DatabaseFactory +import org.whispersystems.signalservice.loki.api.LokiStorageAPI +import org.whispersystems.signalservice.loki.messaging.LokiMessageFriendRequestStatus +import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus +import java.lang.IllegalStateException + +object FriendRequestHandler { + enum class ActionType { Sending, Sent, Failed } + + @JvmStatic + fun handleFriendRequest(context: Context, type: ActionType, messageId: Long, threadId: Long) { + // Update thread status + // Note: Do we need to only update these if we're not friends? + if (threadId >= 0) { + val threadFriendStatus = when (type) { + ActionType.Sending -> LokiThreadFriendRequestStatus.REQUEST_SENDING + ActionType.Failed -> LokiThreadFriendRequestStatus.NONE + ActionType.Sent -> LokiThreadFriendRequestStatus.REQUEST_SENT + } + DatabaseFactory.getLokiThreadDatabase(context).setFriendRequestStatus(threadId, threadFriendStatus) + } + + // Update message status + val recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId) + if (recipient != null && messageId >= 0) { + val messageDatabase = DatabaseFactory.getLokiMessageDatabase(context) + val messageFriendRequestStatus = messageDatabase.getFriendRequestStatus(messageId) + if (type == ActionType.Sending && messageFriendRequestStatus == LokiMessageFriendRequestStatus.NONE) { + // We only want to update message status if we aren't friends with another of their devices + // This avoids spam in the ui where it would keep telling the user that they sent a friend request on every single message + if (!isFriendsWithAnyLinkedDevice(context, recipient)) { + messageDatabase.setFriendRequestStatus(messageId, LokiMessageFriendRequestStatus.REQUEST_SENDING) + } + } else if (messageFriendRequestStatus != LokiMessageFriendRequestStatus.NONE) { + // Update the friend request status of the message if we have it + val messageFriendRequestStatus = when (type) { + ActionType.Failed -> LokiMessageFriendRequestStatus.REQUEST_FAILED + ActionType.Sent -> LokiMessageFriendRequestStatus.REQUEST_PENDING + else -> throw IllegalStateException() + } + messageDatabase.setFriendRequestStatus(messageId, messageFriendRequestStatus) + } + } + } +} \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt b/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt index d1f696ea94..dcbe57652d 100644 --- a/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt +++ b/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt @@ -202,4 +202,32 @@ fun getPrimaryDevicePublicKey(hexEncodedPublicKey: String): String? { } catch (e: Exception) { null } +} + +fun isFriendsWithAnyLinkedDevice(context: Context, recipient: Recipient): Boolean { + if (recipient.isGroupRecipient) return true + val future = SettableFuture() + val storageAPI = LokiStorageAPI.shared + + getAllDeviceFriendRequestStatus(context, recipient.address.serialize(), storageAPI).success { map -> + for (status in map.values) { + if (status == LokiThreadFriendRequestStatus.FRIENDS) { + future.set(true) + break + } + } + + if (!future.isDone) { + future.set(false) + } + }.fail { e -> + future.set(false) + } + + try { + return future.get() + } catch (e: Exception) { + return false + } + } \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/push/MessageSenderEventListener.java b/src/org/thoughtcrime/securesms/push/MessageSenderEventListener.java index e8babe29f5..ec8357b232 100644 --- a/src/org/thoughtcrime/securesms/push/MessageSenderEventListener.java +++ b/src/org/thoughtcrime/securesms/push/MessageSenderEventListener.java @@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.push; import android.content.Context; import org.thoughtcrime.securesms.crypto.SecurityEvent; +import org.thoughtcrime.securesms.loki.FriendRequestHandler; import org.thoughtcrime.securesms.loki.LokiMessageSyncEvent; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.push.SignalServiceAddress; @@ -26,4 +27,16 @@ public class MessageSenderEventListener implements SignalServiceMessageSender.Ev public void onSyncEvent(long messageID, long timestamp, byte[] message, int ttl) { LokiMessageSyncEvent.INSTANCE.broadcastSecurityUpdateEvent(context, messageID, timestamp, message, ttl); } + + @Override public void onFriendRequestSending(long messageID, long threadID) { + FriendRequestHandler.handleFriendRequest(context, FriendRequestHandler.ActionType.Sending, messageID, threadID); + } + + @Override public void onFriendRequestSent(long messageID, long threadID) { + FriendRequestHandler.handleFriendRequest(context, FriendRequestHandler.ActionType.Sent, messageID, threadID); + } + + @Override public void onFriendRequestSendingFail(long messageID, long threadID) { + FriendRequestHandler.handleFriendRequest(context, FriendRequestHandler.ActionType.Failed, messageID, threadID); + } } diff --git a/src/org/thoughtcrime/securesms/sms/MessageSender.java b/src/org/thoughtcrime/securesms/sms/MessageSender.java index 1dd43d402f..e6e9fa254c 100644 --- a/src/org/thoughtcrime/securesms/sms/MessageSender.java +++ b/src/org/thoughtcrime/securesms/sms/MessageSender.java @@ -42,6 +42,7 @@ import org.thoughtcrime.securesms.jobs.SmsSendJob; import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository; import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil; import org.thoughtcrime.securesms.logging.Log; +import org.thoughtcrime.securesms.loki.FriendRequestHandler; import org.thoughtcrime.securesms.loki.GeneralUtilitiesKt; import org.thoughtcrime.securesms.loki.MultiDeviceUtilitiesKt; import org.thoughtcrime.securesms.loki.PushMessageSyncSendJob; @@ -131,7 +132,7 @@ public class MessageSender { // Loki - Set the message's friend request status as soon as it has hit the database if (message.isFriendRequest) { - DatabaseFactory.getLokiMessageDatabase(context).setFriendRequestStatus(messageId, LokiMessageFriendRequestStatus.REQUEST_SENDING); + FriendRequestHandler.handleFriendRequest(context, FriendRequestHandler.ActionType.Sending, messageId, allocatedThreadId); } sendTextMessage(context, recipient, forceSms, keyExchange, messageId); @@ -167,7 +168,7 @@ public class MessageSender { long messageID = database.insertMessageOutbox(message, allocatedThreadId, forceSms, insertListener); // Loki - Set the message's friend request status as soon as it has hit the database if (message.isFriendRequest) { - DatabaseFactory.getLokiMessageDatabase(context).setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_SENDING); + FriendRequestHandler.handleFriendRequest(context, FriendRequestHandler.ActionType.Sending, messageID, allocatedThreadId); } sendMediaMessage(context, recipient, forceSms, messageID, message.getExpiresIn()); } catch (Exception e) { @@ -180,7 +181,7 @@ public class MessageSender { long messageID = database.insertMessageOutbox(message, allocatedThreadId, forceSms, insertListener); // Loki - Set the message's friend request status as soon as it has hit the database if (message.isFriendRequest) { - DatabaseFactory.getLokiMessageDatabase(context).setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_SENDING); + FriendRequestHandler.handleFriendRequest(context, FriendRequestHandler.ActionType.Sending, messageID, allocatedThreadId); } sendMediaMessage(context, recipient, forceSms, messageID, message.getExpiresIn()); } catch (MmsException e) {