Don't render friend requests if we are already friends with a users linked device.

This commit is contained in:
Mikunj 2019-10-25 16:14:15 +11:00
parent 26800cba82
commit 09f5f50af4
6 changed files with 111 additions and 33 deletions

View File

@ -2200,7 +2200,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
inputMethodManager.showSoftInput(inputPanel.composeText, 0); inputMethodManager.showSoftInput(inputPanel.composeText, 0);
} }
boolean hasPendingFriendRequest = !recipient.isGroupRecipient() && hasPendingFriendRequestWithAnyLinkedDevice(); boolean hasPendingFriendRequest = !recipient.isGroupRecipient() && hasPendingFriendRequestWithAnyLinkedDevice();
boolean isFriendsWithAnyLinkedDevices = isFriendsWithAnyLinkedDevice(); boolean isFriendsWithAnyLinkedDevices = MultiDeviceUtilitiesKt.isFriendsWithAnyLinkedDevice(this, recipient);
boolean shouldEnableInput = isFriendsWithAnyLinkedDevices || !hasPendingFriendRequest; boolean shouldEnableInput = isFriendsWithAnyLinkedDevices || !hasPendingFriendRequest;
updateToggleButtonState(); updateToggleButtonState();
inputPanel.setEnabled(shouldEnableInput); inputPanel.setEnabled(shouldEnableInput);
@ -3032,33 +3032,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
updateInputPanel(); updateInputPanel();
} }
public boolean isFriendsWithAnyLinkedDevice() {
if (recipient.isGroupRecipient()) return true;
SettableFuture<Boolean> 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() { public boolean hasPendingFriendRequestWithAnyLinkedDevice() {
if (recipient.isGroupRecipient()) return false; if (recipient.isGroupRecipient()) return false;
SettableFuture<Boolean> future = new SettableFuture<>(); SettableFuture<Boolean> future = new SettableFuture<>();

View File

@ -779,6 +779,11 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
return; 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> insertResult; Optional<InsertResult> insertResult;
try { try {
@ -956,6 +961,11 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
// Ignore the message if the body is empty // Ignore the message if the body is empty
if (textMessage.getMessageBody().length() == 0) { return; } 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 // Insert the message into the database
Optional<InsertResult> insertResult = database.insertMessageInbox(textMessage); Optional<InsertResult> 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) { private void handlePairingMessage(@NonNull PairingAuthorisation authorisation, @NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content) {
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context); String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context);
if (authorisation.getType() == PairingAuthorisation.Type.REQUEST) { if (authorisation.getType() == PairingAuthorisation.Type.REQUEST) {
handlePairingRequestMessage(authorisation, envelope); handlePairingRequestMessage(authorisation);
} else if (authorisation.getSecondaryDevicePublicKey().equals(userHexEncodedPublicKey)) { } else if (authorisation.getSecondaryDevicePublicKey().equals(userHexEncodedPublicKey)) {
handlePairingAuthorisationMessage(authorisation, envelope, content); handlePairingAuthorisationMessage(authorisation, envelope, content);
} }
} }
private void handlePairingRequestMessage(@NonNull PairingAuthorisation authorisation, @NonNull SignalServiceEnvelope envelope) { private void handlePairingRequestMessage(@NonNull PairingAuthorisation authorisation) {
boolean isValid = isValidPairingMessage(authorisation); boolean isValid = isValidPairingMessage(authorisation);
DeviceLinkingSession linkingSession = DeviceLinkingSession.Companion.getShared(); DeviceLinkingSession linkingSession = DeviceLinkingSession.Companion.getShared();
if (isValid && linkingSession.isListeningForLinkingRequests()) { 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. // it must be a friend request accepted message. Declining a friend request doesn't send a message.
lokiThreadDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS); lokiThreadDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS);
// Update the last message if needed // Update the last message if needed
// TODO: Fix this logic to update the last friend request message
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context); SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context); LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context);
int messageCount = smsDatabase.getMessageCountForThread(threadID); int messageCount = smsDatabase.getMessageCountForThread(threadID);
@ -1137,6 +1148,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
// `REQUEST_SENT`. // `REQUEST_SENT`.
lokiThreadDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS); lokiThreadDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS);
// Since messages are forwarded to the primary device thread, we need to update it there // 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 long messageID = smsMessageDatabase.getIDForMessageAtIndex(primaryDeviceThreadID, messageCount - 2); // The message before the one that was just received
lokiMessageDatabase.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED); lokiMessageDatabase.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED);
// Accept the friend request // Accept the friend request

View File

@ -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)
}
}
}
}

View File

@ -203,3 +203,31 @@ fun getPrimaryDevicePublicKey(hexEncodedPublicKey: String): String? {
null null
} }
} }
fun isFriendsWithAnyLinkedDevice(context: Context, recipient: Recipient): Boolean {
if (recipient.isGroupRecipient) return true
val future = SettableFuture<Boolean>()
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
}
}

View File

@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.push;
import android.content.Context; import android.content.Context;
import org.thoughtcrime.securesms.crypto.SecurityEvent; import org.thoughtcrime.securesms.crypto.SecurityEvent;
import org.thoughtcrime.securesms.loki.FriendRequestHandler;
import org.thoughtcrime.securesms.loki.LokiMessageSyncEvent; import org.thoughtcrime.securesms.loki.LokiMessageSyncEvent;
import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.push.SignalServiceAddress; 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) { public void onSyncEvent(long messageID, long timestamp, byte[] message, int ttl) {
LokiMessageSyncEvent.INSTANCE.broadcastSecurityUpdateEvent(context, messageID, timestamp, message, 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);
}
} }

View File

@ -42,6 +42,7 @@ import org.thoughtcrime.securesms.jobs.SmsSendJob;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository; import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil; import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.loki.FriendRequestHandler;
import org.thoughtcrime.securesms.loki.GeneralUtilitiesKt; import org.thoughtcrime.securesms.loki.GeneralUtilitiesKt;
import org.thoughtcrime.securesms.loki.MultiDeviceUtilitiesKt; import org.thoughtcrime.securesms.loki.MultiDeviceUtilitiesKt;
import org.thoughtcrime.securesms.loki.PushMessageSyncSendJob; 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 // Loki - Set the message's friend request status as soon as it has hit the database
if (message.isFriendRequest) { 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); sendTextMessage(context, recipient, forceSms, keyExchange, messageId);
@ -167,7 +168,7 @@ public class MessageSender {
long messageID = database.insertMessageOutbox(message, allocatedThreadId, forceSms, insertListener); long messageID = database.insertMessageOutbox(message, allocatedThreadId, forceSms, insertListener);
// Loki - Set the message's friend request status as soon as it has hit the database // Loki - Set the message's friend request status as soon as it has hit the database
if (message.isFriendRequest) { 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()); sendMediaMessage(context, recipient, forceSms, messageID, message.getExpiresIn());
} catch (Exception e) { } catch (Exception e) {
@ -180,7 +181,7 @@ public class MessageSender {
long messageID = database.insertMessageOutbox(message, allocatedThreadId, forceSms, insertListener); long messageID = database.insertMessageOutbox(message, allocatedThreadId, forceSms, insertListener);
// Loki - Set the message's friend request status as soon as it has hit the database // Loki - Set the message's friend request status as soon as it has hit the database
if (message.isFriendRequest) { 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()); sendMediaMessage(context, recipient, forceSms, messageID, message.getExpiresIn());
} catch (MmsException e) { } catch (MmsException e) {