More fixes for friend request UI for multi device.

Remove old FR pending states on new incoming friend request.
Always update the last friend request message state and not a new message.
This commit is contained in:
Mikunj 2019-10-29 11:23:30 +11:00
parent 09f5f50af4
commit 9ea2a6c8e4
6 changed files with 84 additions and 35 deletions

View File

@ -47,6 +47,7 @@ import org.whispersystems.libsignal.util.guava.Optional;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@ -193,6 +194,23 @@ public class SmsDatabase extends MessagingDatabase {
return -1;
}
public Set<Long> getAllMessageIDs(long threadID) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
Cursor cursor = null;
Set<Long> messageIDs = new HashSet<>();
try {
cursor = database.query(TABLE_NAME, null, THREAD_ID + " = ?", new String[] { threadID + "" }, null, null, null);
while (cursor != null && cursor.moveToNext()) {
messageIDs.add(cursor.getLong(0));
}
} finally {
if (cursor != null) {
cursor.close();
}
}
return messageIDs;
}
public void markAsEndSession(long id) {
updateTypeBitmask(id, Types.KEY_EXCHANGE_MASK, Types.END_SESSION_BIT);
}

View File

@ -66,6 +66,7 @@ import org.thoughtcrime.securesms.linkpreview.Link;
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.loki.FriendRequestHandler;
import org.thoughtcrime.securesms.loki.LokiAPIUtilities;
import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
import org.thoughtcrime.securesms.loki.LokiPreKeyBundleDatabase;
@ -961,11 +962,6 @@ 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> insertResult = database.insertMessageInbox(textMessage);
@ -1103,14 +1099,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);
long messageID = smsDatabase.getIDForMessageAtIndex(threadID, messageCount - 1);
if (messageID > -1 && lokiMessageDatabase.getFriendRequestStatus(messageID) != LokiMessageFriendRequestStatus.REQUEST_ACCEPTED) {
lokiMessageDatabase.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED);
}
FriendRequestHandler.updateLastFriendRequestMessage(context, threadID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED);
}
private void updateFriendRequestStatusIfNeeded(@NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) {
@ -1134,7 +1123,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(originalRecipient);
long primaryDeviceThreadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(primaryDeviceRecipient);
LokiThreadFriendRequestStatus threadFriendRequestStatus = lokiThreadDatabase.getFriendRequestStatus(threadID);
int messageCount = smsMessageDatabase.getMessageCountForThread(primaryDeviceThreadID);
if (threadFriendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENT) {
// This can happen if Alice sent Bob a friend request, Bob declined, but then Bob changed his
// mind and sent a friend request to Alice. In this case we want Alice to auto-accept the request
@ -1148,9 +1137,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);
FriendRequestHandler.updateLastFriendRequestMessage(context, primaryDeviceThreadID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED);
// Accept the friend request
MessageSender.sendBackgroundMessage(context, content.getSender());
} else if (threadFriendRequestStatus != LokiThreadFriendRequestStatus.FRIENDS) {
@ -1160,10 +1147,9 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
// request. Alice's thread's friend request status is reset to
// `REQUEST_RECEIVED`.
lokiThreadDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.REQUEST_RECEIVED);
// Since messages are forwarded to the primary device thread, we need to update it there
long smsMessageID = smsMessageDatabase.getIDForMessageAtIndex(primaryDeviceThreadID, messageCount - 1); // The message that was just received
long messageID = smsMessageID != -1 ? smsMessageID : mmsMessageDatabase.getIDForMessageAtIndex(primaryDeviceThreadID, 0);
lokiMessageDatabase.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_PENDING);
FriendRequestHandler.receivedIncomingFriendRequestMessage(context, primaryDeviceThreadID);
}
}
}

View File

@ -14,7 +14,7 @@ object FriendRequestHandler {
enum class ActionType { Sending, Sent, Failed }
@JvmStatic
fun handleFriendRequest(context: Context, type: ActionType, messageId: Long, threadId: Long) {
fun updateFriendRequestState(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) {
@ -30,14 +30,14 @@ object FriendRequestHandler {
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) {
val friendRequestStatus = messageDatabase.getFriendRequestStatus(messageId)
if (type == ActionType.Sending) {
// 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)) {
if (!isFriendsWithAnyLinkedDevice(context, recipient) && friendRequestStatus == LokiMessageFriendRequestStatus.NONE) {
messageDatabase.setFriendRequestStatus(messageId, LokiMessageFriendRequestStatus.REQUEST_SENDING)
}
} else if (messageFriendRequestStatus != LokiMessageFriendRequestStatus.NONE) {
} else if (friendRequestStatus != LokiMessageFriendRequestStatus.NONE) {
// Update the friend request status of the message if we have it
val messageFriendRequestStatus = when (type) {
ActionType.Failed -> LokiMessageFriendRequestStatus.REQUEST_FAILED
@ -48,4 +48,45 @@ object FriendRequestHandler {
}
}
}
@JvmStatic
fun updateLastFriendRequestMessage(context: Context, threadId: Long, status: LokiMessageFriendRequestStatus) {
if (threadId < 0) { return }
val messages = DatabaseFactory.getSmsDatabase(context).getAllMessageIDs(threadId)
val lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context)
val lastMessage = messages.find {
val friendRequestStatus = lokiMessageDatabase.getFriendRequestStatus(it)
friendRequestStatus == LokiMessageFriendRequestStatus.REQUEST_PENDING
} ?: return
DatabaseFactory.getLokiMessageDatabase(context).setFriendRequestStatus(lastMessage, status)
}
@JvmStatic
fun receivedIncomingFriendRequestMessage(context: Context, threadId: Long) {
val smsMessageDatabase = DatabaseFactory.getSmsDatabase(context)
// We only want to update the last message status if we're not friends with any of their linked devices
// This ensures that we don't spam the UI with accept/decline messages
val recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId) ?: return
if (isFriendsWithAnyLinkedDevice(context, recipient)) { return }
// Since messages are forwarded to the primary device thread, we need to update it there
val messageCount = smsMessageDatabase.getMessageCountForThread(threadId)
val messageID = smsMessageDatabase.getIDForMessageAtIndex(threadId, messageCount - 1) // The message that was just received
if (messageID < 0) { return }
val messageDatabase = DatabaseFactory.getLokiMessageDatabase(context)
// We need to go through and set all messages which are REQUEST_PENDING to NONE
smsMessageDatabase.getAllMessageIDs(threadId)
.filter { messageDatabase.getFriendRequestStatus(it) == LokiMessageFriendRequestStatus.REQUEST_PENDING }
.forEach {
messageDatabase.setFriendRequestStatus(it, LokiMessageFriendRequestStatus.NONE)
}
// Set the last message to pending
messageDatabase.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_PENDING)
}
}

View File

@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.loki
import android.content.Context
import android.os.Handler
import nl.komponents.kovenant.Promise
import nl.komponents.kovenant.deferred
import nl.komponents.kovenant.functional.bind
@ -134,9 +135,13 @@ fun signAndSendPairingAuthorisationMessage(context: Context, pairingAuthorisatio
Log.d("Loki", "Failed to send pairing authorization message to ${pairingAuthorisation.secondaryDevicePublicKey}.")
}
DatabaseFactory.getLokiAPIDatabase(context).insertOrUpdatePairingAuthorisation(signedPairingAuthorisation)
LokiStorageAPI.shared.updateUserDeviceMappings().fail { exception ->
Log.w("Loki", "Failed to update device mapping")
}
// Call function after a short delay
Handler().postDelayed({
LokiStorageAPI.shared.updateUserDeviceMappings().fail {
Log.w("Loki", "Failed to update device mapping")
}
}, 100)
}
fun shouldSendSycMessage(context: Context, address: Address): Boolean {

View File

@ -29,14 +29,14 @@ public class MessageSenderEventListener implements SignalServiceMessageSender.Ev
}
@Override public void onFriendRequestSending(long messageID, long threadID) {
FriendRequestHandler.handleFriendRequest(context, FriendRequestHandler.ActionType.Sending, messageID, threadID);
FriendRequestHandler.updateFriendRequestState(context, FriendRequestHandler.ActionType.Sending, messageID, threadID);
}
@Override public void onFriendRequestSent(long messageID, long threadID) {
FriendRequestHandler.handleFriendRequest(context, FriendRequestHandler.ActionType.Sent, messageID, threadID);
FriendRequestHandler.updateFriendRequestState(context, FriendRequestHandler.ActionType.Sent, messageID, threadID);
}
@Override public void onFriendRequestSendingFail(long messageID, long threadID) {
FriendRequestHandler.handleFriendRequest(context, FriendRequestHandler.ActionType.Failed, messageID, threadID);
FriendRequestHandler.updateFriendRequestState(context, FriendRequestHandler.ActionType.Failed, messageID, threadID);
}
}

View File

@ -60,7 +60,6 @@ import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import org.whispersystems.signalservice.api.push.ContactTokenDetails;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
import org.whispersystems.signalservice.loki.messaging.LokiMessageFriendRequestStatus;
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus;
import java.io.IOException;
@ -132,7 +131,7 @@ public class MessageSender {
// Loki - Set the message's friend request status as soon as it has hit the database
if (message.isFriendRequest) {
FriendRequestHandler.handleFriendRequest(context, FriendRequestHandler.ActionType.Sending, messageId, allocatedThreadId);
FriendRequestHandler.updateFriendRequestState(context, FriendRequestHandler.ActionType.Sending, messageId, allocatedThreadId);
}
sendTextMessage(context, recipient, forceSms, keyExchange, messageId);
@ -168,7 +167,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) {
FriendRequestHandler.handleFriendRequest(context, FriendRequestHandler.ActionType.Sending, messageID, allocatedThreadId);
FriendRequestHandler.updateFriendRequestState(context, FriendRequestHandler.ActionType.Sending, messageID, allocatedThreadId);
}
sendMediaMessage(context, recipient, forceSms, messageID, message.getExpiresIn());
} catch (Exception e) {
@ -181,7 +180,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) {
FriendRequestHandler.handleFriendRequest(context, FriendRequestHandler.ActionType.Sending, messageID, allocatedThreadId);
FriendRequestHandler.updateFriendRequestState(context, FriendRequestHandler.ActionType.Sending, messageID, allocatedThreadId);
}
sendMediaMessage(context, recipient, forceSms, messageID, message.getExpiresIn());
} catch (MmsException e) {