mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 20:15:21 +00:00
Stop main thread from being blocked.
Refactoring.
This commit is contained in:
parent
4072f506b5
commit
31ad7a40de
@ -91,8 +91,7 @@ public class TypingStatusSender {
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new TypingSendJob(threadId, typingStarted));
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> devices = LokiStorageAPI.shared.getAllDevicePublicKeys(recipient.getAddress().serialize());
|
||||
LokiStorageAPI.shared.getAllDevicePublicKeysAsync(recipient.getAddress().serialize()).success(devices -> {
|
||||
for (String device : devices) {
|
||||
Recipient deviceRecipient = Recipient.from(context, Address.fromSerialized(device), false);
|
||||
long deviceThreadID = threadDatabase.getThreadIdIfExistsFor(deviceRecipient);
|
||||
@ -100,6 +99,8 @@ public class TypingStatusSender {
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new TypingSendJob(deviceThreadID, typingStarted));
|
||||
}
|
||||
}
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
}
|
||||
|
||||
private class StartRunnable implements Runnable {
|
||||
|
@ -249,7 +249,11 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import kotlin.Unit;
|
||||
import network.loki.messenger.R;
|
||||
import nl.komponents.kovenant.Kovenant;
|
||||
import nl.komponents.kovenant.KovenantApi;
|
||||
import nl.komponents.kovenant.Promise;
|
||||
|
||||
import static nl.komponents.kovenant.KovenantApi.task;
|
||||
import static org.thoughtcrime.securesms.TransportOption.Type;
|
||||
import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
|
||||
import static org.whispersystems.libsignal.SessionCipher.SESSION_LOCK;
|
||||
@ -2185,44 +2189,50 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
@Override
|
||||
public void handleThreadFriendRequestStatusChanged(long threadID) {
|
||||
Util.runOnMain(() -> {
|
||||
boolean shouldUpdateInputPanel = true;
|
||||
if (threadID != this.threadId) {
|
||||
Recipient threadRecipient = DatabaseFactory.getThreadDatabase(this).getRecipientForThreadId(threadID);
|
||||
if (threadRecipient != null && !threadRecipient.isGroupRecipient()) {
|
||||
LokiStorageAPI.shared.getAllDevicePublicKeysAsync(threadRecipient.getAddress().serialize()).success(devices -> {
|
||||
// We should update our input if this thread is a part of the other threads device
|
||||
Set<String> devices = LokiStorageAPI.shared.getAllDevicePublicKeys(threadRecipient.getAddress().serialize());
|
||||
shouldUpdateInputPanel = devices.contains(recipient.getAddress().serialize());
|
||||
} else {
|
||||
shouldUpdateInputPanel = false;
|
||||
}
|
||||
}
|
||||
if (shouldUpdateInputPanel) {
|
||||
if (devices.contains(recipient.getAddress().serialize())) {
|
||||
this.updateInputPanel();
|
||||
}
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateInputPanel();
|
||||
}
|
||||
|
||||
private void updateInputPanel() {
|
||||
if (recipient.isGroupRecipient()) {
|
||||
updateToggleButtonState();
|
||||
inputPanel.setEnabled(true);
|
||||
inputPanel.composeText.requestFocus();
|
||||
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
|
||||
inputMethodManager.showSoftInput(inputPanel.composeText, 0);
|
||||
if (recipient.isGroupRecipient() || isNoteToSelf()) {
|
||||
setInputPanelEnabled(true);
|
||||
return;
|
||||
}
|
||||
boolean hasPendingFriendRequest = !recipient.isGroupRecipient() && hasPendingFriendRequestWithAnyLinkedDevice();
|
||||
boolean isFriendsWithAnyLinkedDevices = MultiDeviceUtilities.isFriendsWithAnyLinkedDevice(this, recipient);
|
||||
boolean shouldEnableInput = isFriendsWithAnyLinkedDevices || !hasPendingFriendRequest;
|
||||
|
||||
task(() -> {
|
||||
// Run the functions below in a background thread since they are blocking
|
||||
return MultiDeviceUtilities.isFriendsWithAnyLinkedDevice(this, recipient) || !hasPendingFriendRequestWithAnyLinkedDevice();
|
||||
}).success(shouldEnableInput -> {
|
||||
setInputPanelEnabled(shouldEnableInput);
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
}
|
||||
|
||||
private void setInputPanelEnabled(boolean enabled) {
|
||||
Util.runOnMain(() -> {
|
||||
updateToggleButtonState();
|
||||
inputPanel.setEnabled(shouldEnableInput);
|
||||
int hintID = shouldEnableInput ? R.string.activity_conversation_default_hint : R.string.activity_conversation_pending_friend_request_hint;
|
||||
int hintID = enabled ? R.string.activity_conversation_default_hint : R.string.activity_conversation_pending_friend_request_hint;
|
||||
inputPanel.setHint(getResources().getString(hintID));
|
||||
if (shouldEnableInput) {
|
||||
inputPanel.setEnabled(enabled);
|
||||
if (enabled) {
|
||||
inputPanel.composeText.requestFocus();
|
||||
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
|
||||
inputMethodManager.showSoftInput(inputPanel.composeText, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void sendMessage() {
|
||||
@ -2428,7 +2438,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private void updateToggleButtonState() {
|
||||
// Don't allow attachments if we're not friends
|
||||
LokiThreadFriendRequestStatus friendRequestStatus = DatabaseFactory.getLokiThreadDatabase(this).getFriendRequestStatus(threadId);
|
||||
if (!recipient.isGroupRecipient() && friendRequestStatus != LokiThreadFriendRequestStatus.FRIENDS) {
|
||||
if (!isNoteToSelf() && !recipient.isGroupRecipient() && friendRequestStatus != LokiThreadFriendRequestStatus.FRIENDS) {
|
||||
buttonToggle.display(sendButton);
|
||||
quickAttachmentToggle.hide();
|
||||
inlineAttachmentToggle.hide();
|
||||
@ -3047,6 +3057,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
public boolean hasPendingFriendRequestWithAnyLinkedDevice() {
|
||||
if (recipient.isGroupRecipient()) return false;
|
||||
|
||||
// This call will block the thread that is being run on! be careful
|
||||
Map<String, LokiThreadFriendRequestStatus> map = MultiDeviceUtilities.getAllDeviceFriendRequestStatuses(this, recipient.getAddress().serialize());
|
||||
for (LokiThreadFriendRequestStatus status : map.values()) {
|
||||
if (status == LokiThreadFriendRequestStatus.REQUEST_SENDING || status == LokiThreadFriendRequestStatus.REQUEST_SENT || status == LokiThreadFriendRequestStatus.REQUEST_RECEIVED) {
|
||||
@ -3056,5 +3067,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isNoteToSelf() {
|
||||
return TextSecurePreferences.getLocalNumber(this).equalsIgnoreCase(recipient.getAddress().serialize());
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ package org.thoughtcrime.securesms.loki
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import nl.komponents.kovenant.Promise
|
||||
import nl.komponents.kovenant.functional.map
|
||||
import nl.komponents.kovenant.toFailVoid
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
||||
import org.thoughtcrime.securesms.database.Address
|
||||
@ -20,6 +22,10 @@ import org.whispersystems.signalservice.loki.api.PairingAuthorisation
|
||||
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus
|
||||
import org.whispersystems.signalservice.loki.utilities.retryIfNeeded
|
||||
|
||||
/*
|
||||
All functions within this class, excluding the ones which return promises, BLOCK the thread! Don't run them on the main thread!
|
||||
*/
|
||||
|
||||
fun getAllDeviceFriendRequestStatuses(context: Context, hexEncodedPublicKey: String): Map<String, LokiThreadFriendRequestStatus> {
|
||||
val lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
val keys = LokiStorageAPI.shared.getAllDevicePublicKeys(hexEncodedPublicKey)
|
||||
@ -33,18 +39,20 @@ fun getAllDeviceFriendRequestStatuses(context: Context, hexEncodedPublicKey: Str
|
||||
return map
|
||||
}
|
||||
|
||||
fun getAllDevicePublicKeysWithFriendStatus(context: Context, hexEncodedPublicKey: String): Map<String, Boolean> {
|
||||
fun getAllDevicePublicKeysWithFriendStatus(context: Context, hexEncodedPublicKey: String): Promise<Map<String, Boolean>, Unit> {
|
||||
val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||
val devices = LokiStorageAPI.shared.getAllDevicePublicKeys(hexEncodedPublicKey).toMutableSet()
|
||||
return LokiStorageAPI.shared.getAllDevicePublicKeysAsync(hexEncodedPublicKey).map { keys ->
|
||||
val devices = keys.toMutableSet()
|
||||
if (hexEncodedPublicKey != userHexEncodedPublicKey) {
|
||||
devices.remove(userHexEncodedPublicKey)
|
||||
}
|
||||
val friends = getFriendPublicKeys(context, devices)
|
||||
val map = mutableMapOf<String, Boolean>()
|
||||
val friendMap = mutableMapOf<String, Boolean>()
|
||||
for (device in devices) {
|
||||
map[device] = friends.contains(device)
|
||||
friendMap[device] = friends.contains(device)
|
||||
}
|
||||
return map
|
||||
friendMap
|
||||
}.toFailVoid()
|
||||
}
|
||||
|
||||
fun getFriendCount(context: Context, devices: Set<String>): Int {
|
||||
|
@ -39,6 +39,7 @@ class PushMessageSyncSendJob private constructor(
|
||||
|
||||
constructor(messageID: Long, recipient: Address, timestamp: Long, message: ByteArray, ttl: Int) : this(Parameters.Builder()
|
||||
.addConstraint(NetworkConstraint.KEY)
|
||||
.setQueue(KEY)
|
||||
.setLifespan(TimeUnit.DAYS.toMillis(1))
|
||||
.setMaxAttempts(3)
|
||||
.build(),
|
||||
|
@ -22,7 +22,6 @@ import org.thoughtcrime.securesms.util.Hex
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.curve25519.Curve25519
|
||||
import org.whispersystems.libsignal.util.KeyHelper
|
||||
import org.whispersystems.signalservice.loki.api.LokiStorageAPI
|
||||
import org.whispersystems.signalservice.loki.api.PairingAuthorisation
|
||||
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
|
||||
import org.whispersystems.signalservice.loki.utilities.Analytics
|
||||
|
@ -22,6 +22,7 @@ import org.thoughtcrime.securesms.jobs.SendReadReceiptJob;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
|
||||
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
|
||||
|
||||
import java.util.LinkedList;
|
||||
@ -29,6 +30,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import kotlin.Unit;
|
||||
import kotlin.contracts.Returns;
|
||||
|
||||
public class MarkReadReceiver extends BroadcastReceiver {
|
||||
|
||||
@ -91,16 +93,17 @@ public class MarkReadReceiver extends BroadcastReceiver {
|
||||
|
||||
for (Address address : addressMap.keySet()) {
|
||||
List<Long> timestamps = Stream.of(addressMap.get(address)).map(SyncMessageId::getTimetamp).toList();
|
||||
|
||||
Map<String, Boolean> devices = MultiDeviceUtilities.getAllDevicePublicKeysWithFriendStatus(context, address.serialize());
|
||||
MultiDeviceUtilities.getAllDevicePublicKeysWithFriendStatus(context, address.serialize()).success(devices -> {
|
||||
for (Map.Entry<String, Boolean> entry : devices.entrySet()) {
|
||||
String device = entry.getKey();
|
||||
boolean isFriend = entry.getValue();
|
||||
// Loki - This also prevents read receipts from being sent in group chats as they don't maintain a friend request status
|
||||
if (isFriend) {
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new SendReadReceiptJob(Address.fromSerialized(device), timestamps));
|
||||
Util.runOnMain(() -> ApplicationContext.getInstance(context).getJobManager().add(new SendReadReceiptJob(Address.fromSerialized(device), timestamps)));
|
||||
}
|
||||
}
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,8 @@ public class MessageSender {
|
||||
|
||||
private static final String TAG = MessageSender.class.getSimpleName();
|
||||
|
||||
private enum MessageType { TEXT, MEDIA }
|
||||
|
||||
public static void sendBackgroundMessageToAllDevices(Context context, String contactHexEncodedPublicKey) {
|
||||
// Send the background message to the original pubkey
|
||||
sendBackgroundMessage(context, contactHexEncodedPublicKey);
|
||||
@ -254,26 +256,32 @@ public class MessageSender {
|
||||
}
|
||||
|
||||
private static void sendTextPush(Context context, Recipient recipient, long messageId) {
|
||||
sendMessagePush(context, MessageType.TEXT, recipient, messageId);
|
||||
}
|
||||
|
||||
private static void sendMediaPush(Context context, Recipient recipient, long messageId) {
|
||||
sendMessagePush(context, MessageType.MEDIA, recipient, messageId);
|
||||
}
|
||||
|
||||
private static void sendMessagePush(Context context, MessageType type, Recipient recipient, long messageId) {
|
||||
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
|
||||
|
||||
// Just send the message normally if it's a group message
|
||||
// Just send the message normally if it's a group message or we're sending to one of our devices
|
||||
// TODO: Test how badly this will block the thread
|
||||
String recipientPublicKey = recipient.getAddress().serialize();
|
||||
if (GeneralUtilitiesKt.isPublicChat(context, recipientPublicKey)) {
|
||||
if (GeneralUtilitiesKt.isPublicChat(context, recipientPublicKey) || MultiDeviceUtilities.isOneOfOurDevices(context, recipient.getAddress())) {
|
||||
if (type == MessageType.MEDIA) {
|
||||
PushMediaSendJob.enqueue(context, jobManager, messageId, recipient.getAddress(), false);
|
||||
} else {
|
||||
jobManager.add(new PushTextSendJob(messageId, recipient.getAddress()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Note to self
|
||||
boolean isNoteToSelf = MultiDeviceUtilities.isOneOfOurDevices(context, recipient.getAddress());
|
||||
if (isNoteToSelf) {
|
||||
jobManager.add(new PushTextSendJob(messageId, recipient.getAddress()));
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hasSentSyncMessage = false;
|
||||
|
||||
Map<String, Boolean> devices = MultiDeviceUtilities.getAllDevicePublicKeysWithFriendStatus(context, recipientPublicKey);
|
||||
boolean[] hasSentSyncMessage = { false };
|
||||
MultiDeviceUtilities.getAllDevicePublicKeysWithFriendStatus(context, recipientPublicKey).success(devices -> {
|
||||
int friendCount = MultiDeviceUtilities.getFriendCount(context, devices.keySet());
|
||||
Util.runOnMain(() -> {
|
||||
for (Map.Entry<String, Boolean> entry : devices.entrySet()) {
|
||||
String devicePublicKey = entry.getKey();
|
||||
boolean isFriend = entry.getValue();
|
||||
@ -284,61 +292,28 @@ public class MessageSender {
|
||||
if (isFriend) {
|
||||
// Send a normal message if the user is friends with the recipient
|
||||
// We should also send a sync message if we haven't already sent one
|
||||
boolean shouldSendSyncMessage = !hasSentSyncMessage && MultiDeviceUtilities.shouldSendSycMessage(context, address);
|
||||
boolean shouldSendSyncMessage = !hasSentSyncMessage[0] && MultiDeviceUtilities.shouldSendSycMessage(context, address);
|
||||
if (type == MessageType.MEDIA) {
|
||||
PushMediaSendJob.enqueue(context, jobManager, messageId, messageIDToUse, address, shouldSendSyncMessage);
|
||||
} else {
|
||||
jobManager.add(new PushTextSendJob(messageId, messageIDToUse, address, shouldSendSyncMessage));
|
||||
hasSentSyncMessage = shouldSendSyncMessage;
|
||||
}
|
||||
hasSentSyncMessage[0] = shouldSendSyncMessage;
|
||||
} else {
|
||||
// Send friend requests to non friends. If the user is friends with any
|
||||
// of the devices then send out a default friend request message.
|
||||
boolean isFriendsWithAny = (friendCount > 0);
|
||||
String defaultFriendRequestMessage = isFriendsWithAny ? "Accept this friend request to enable messages to be synced across devices" : null;
|
||||
if (type == MessageType.MEDIA) {
|
||||
PushMediaSendJob.enqueue(context, jobManager, messageId, messageIDToUse, address, true, defaultFriendRequestMessage, false);
|
||||
} else {
|
||||
jobManager.add(new PushTextSendJob(messageId, messageIDToUse, address, true, defaultFriendRequestMessage, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendMediaPush(Context context, Recipient recipient, long messageId) {
|
||||
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
|
||||
|
||||
// Just send the message normally if it's a group message
|
||||
String recipientPublicKey = recipient.getAddress().serialize();
|
||||
if (GeneralUtilitiesKt.isPublicChat(context, recipientPublicKey)) {
|
||||
PushMediaSendJob.enqueue(context, jobManager, messageId, recipient.getAddress(), false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Note to self
|
||||
boolean isNoteToSelf = MultiDeviceUtilities.isOneOfOurDevices(context, recipient.getAddress());
|
||||
if (isNoteToSelf) {
|
||||
jobManager.add(new PushTextSendJob(messageId, recipient.getAddress()));
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hasSentSyncMessage = false;
|
||||
|
||||
Map<String, Boolean> devices = MultiDeviceUtilities.getAllDevicePublicKeysWithFriendStatus(context, recipientPublicKey);
|
||||
int friendCount = MultiDeviceUtilities.getFriendCount(context, devices.keySet());
|
||||
for (Map.Entry<String, Boolean> entry : devices.entrySet()) {
|
||||
String devicePublicKey = entry.getKey();
|
||||
boolean isFriend = entry.getValue();
|
||||
|
||||
Address address = Address.fromSerialized(devicePublicKey);
|
||||
long messageIDToUse = recipientPublicKey.equals(devicePublicKey) ? messageId : -1L;
|
||||
|
||||
if (isFriend) {
|
||||
// Send a normal message if the user is friends with the recipient
|
||||
// We should also send a sync message if we haven't already sent one
|
||||
boolean shouldSendSyncMessage = !hasSentSyncMessage && MultiDeviceUtilities.shouldSendSycMessage(context, address);
|
||||
PushMediaSendJob.enqueue(context, jobManager, messageId, messageIDToUse, address, shouldSendSyncMessage);
|
||||
hasSentSyncMessage = shouldSendSyncMessage;
|
||||
} else {
|
||||
// Send friend requests to non friends. If the user is friends with any
|
||||
// of the devices then send out a default friend request message.
|
||||
boolean isFriendsWithAny = (friendCount > 0);
|
||||
String defaultFriendRequestMessage = isFriendsWithAny ? "Accept this friend request to enable messages to be synced across devices" : null;
|
||||
PushMediaSendJob.enqueue(context, jobManager, messageId, messageIDToUse, address, true, defaultFriendRequestMessage, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
}
|
||||
|
||||
private static void sendGroupPush(Context context, Recipient recipient, long messageId, Address filterAddress) {
|
||||
|
@ -640,7 +640,7 @@ public class TextSecurePreferences {
|
||||
}
|
||||
|
||||
public static void setLocalNumber(Context context, String localNumber) {
|
||||
setStringPreference(context, LOCAL_NUMBER_PREF, localNumber);
|
||||
setStringPreference(context, LOCAL_NUMBER_PREF, localNumber.toLowerCase());
|
||||
}
|
||||
|
||||
public static void removeLocalNumber(Context context) {
|
||||
|
Loading…
Reference in New Issue
Block a user