Cleanup code.

This commit is contained in:
Mikunj 2019-10-30 09:59:11 +11:00
parent 3298d665e9
commit 7ff7c36e27
11 changed files with 156 additions and 287 deletions

View File

@ -44,7 +44,7 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import org.thoughtcrime.securesms.loki.DeviceLinkingDialog; import org.thoughtcrime.securesms.loki.DeviceLinkingDialog;
import org.thoughtcrime.securesms.loki.DeviceLinkingDialogDelegate; import org.thoughtcrime.securesms.loki.DeviceLinkingDialogDelegate;
import org.thoughtcrime.securesms.loki.DeviceLinkingView; import org.thoughtcrime.securesms.loki.DeviceLinkingView;
import org.thoughtcrime.securesms.loki.MultiDeviceUtilitiesKt; import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
import org.thoughtcrime.securesms.loki.QRCodeDialog; import org.thoughtcrime.securesms.loki.QRCodeDialog;
import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment; import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment;
import org.thoughtcrime.securesms.preferences.ChatsPreferenceFragment; import org.thoughtcrime.securesms.preferences.ChatsPreferenceFragment;
@ -394,7 +394,7 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
} }
@Override public void sendPairingAuthorizedMessage(@NotNull PairingAuthorisation pairingAuthorisation) { @Override public void sendPairingAuthorizedMessage(@NotNull PairingAuthorisation pairingAuthorisation) {
MultiDeviceUtilitiesKt.signAndSendPairingAuthorisationMessage(context, pairingAuthorisation); MultiDeviceUtilities.signAndSendPairingAuthorisationMessage(context, pairingAuthorisation);
} }
@Override public void handleDeviceLinkAuthorized(@NotNull PairingAuthorisation pairingAuthorisation) {} @Override public void handleDeviceLinkAuthorized(@NotNull PairingAuthorisation pairingAuthorisation) {}
@Override public void handleDeviceLinkingDialogDismissed() {} @Override public void handleDeviceLinkingDialogDismissed() {}

View File

@ -9,13 +9,14 @@ import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.jobs.TypingSendJob; import org.thoughtcrime.securesms.jobs.TypingSendJob;
import org.thoughtcrime.securesms.loki.MultiDeviceUtilitiesKt; import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.signalservice.loki.api.LokiStorageAPI; import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import kotlin.Unit; import kotlin.Unit;
@ -91,14 +92,14 @@ public class TypingStatusSender {
return; return;
} }
MultiDeviceUtilitiesKt.getAllDevicePublicKeys(context, recipient.getAddress().serialize(), storageAPI, (devicePublicKey, isFriend, friendCount) -> { Set<String> devices = LokiStorageAPI.shared.getAllDevicePublicKeys(recipient.getAddress().serialize());
Recipient device = Recipient.from(context, Address.fromSerialized(devicePublicKey), false); for (String device : devices) {
long deviceThreadID = threadDatabase.getThreadIdIfExistsFor(device); Recipient deviceRecipient = Recipient.from(context, Address.fromSerialized(device), false);
long deviceThreadID = threadDatabase.getThreadIdIfExistsFor(deviceRecipient);
if (deviceThreadID > -1) { if (deviceThreadID > -1) {
ApplicationContext.getInstance(context).getJobManager().add(new TypingSendJob(deviceThreadID, typingStarted)); ApplicationContext.getInstance(context).getJobManager().add(new TypingSendJob(deviceThreadID, typingStarted));
} }
return Unit.INSTANCE; }
});
} }
private class StartRunnable implements Runnable { private class StartRunnable implements Runnable {

View File

@ -38,7 +38,6 @@ import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator; import android.os.Vibrator;
import android.provider.Browser; import android.provider.Browser;
import android.provider.ContactsContract; import android.provider.ContactsContract;
@ -128,7 +127,6 @@ import org.thoughtcrime.securesms.contactshare.SimpleTextWatcher;
import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable; import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
import org.thoughtcrime.securesms.crypto.SecurityEvent; import org.thoughtcrime.securesms.crypto.SecurityEvent;
import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.Database;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.DraftDatabase; import org.thoughtcrime.securesms.database.DraftDatabase;
import org.thoughtcrime.securesms.database.DraftDatabase.Draft; import org.thoughtcrime.securesms.database.DraftDatabase.Draft;
@ -163,7 +161,7 @@ import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
import org.thoughtcrime.securesms.loki.LokiThreadDatabaseDelegate; import org.thoughtcrime.securesms.loki.LokiThreadDatabaseDelegate;
import org.thoughtcrime.securesms.loki.LokiUserDatabase; import org.thoughtcrime.securesms.loki.LokiUserDatabase;
import org.thoughtcrime.securesms.loki.MentionCandidateSelectionView; import org.thoughtcrime.securesms.loki.MentionCandidateSelectionView;
import org.thoughtcrime.securesms.loki.MultiDeviceUtilitiesKt; import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
import org.thoughtcrime.securesms.mediasend.Media; import org.thoughtcrime.securesms.mediasend.Media;
import org.thoughtcrime.securesms.mediasend.MediaSendActivity; import org.thoughtcrime.securesms.mediasend.MediaSendActivity;
import org.thoughtcrime.securesms.mms.AttachmentManager; import org.thoughtcrime.securesms.mms.AttachmentManager;
@ -228,9 +226,6 @@ import org.thoughtcrime.securesms.util.concurrent.SettableFuture;
import org.thoughtcrime.securesms.util.views.Stub; import org.thoughtcrime.securesms.util.views.Stub;
import org.whispersystems.libsignal.InvalidMessageException; import org.whispersystems.libsignal.InvalidMessageException;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.loki.api.LokiAPI; import org.whispersystems.signalservice.loki.api.LokiAPI;
import org.whispersystems.signalservice.loki.api.LokiStorageAPI; import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
import org.whispersystems.signalservice.loki.messaging.LokiMessageFriendRequestStatus; import org.whispersystems.signalservice.loki.messaging.LokiMessageFriendRequestStatus;
@ -246,6 +241,7 @@ import java.util.Date;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -2195,7 +2191,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
Recipient threadRecipient = DatabaseFactory.getThreadDatabase(this).getRecipientForThreadId(threadID); Recipient threadRecipient = DatabaseFactory.getThreadDatabase(this).getRecipientForThreadId(threadID);
if (threadRecipient != null && !threadRecipient.isGroupRecipient()) { if (threadRecipient != null && !threadRecipient.isGroupRecipient()) {
// We should update our input if this thread is a part of the other threads device // We should update our input if this thread is a part of the other threads device
Set<String> devices = MultiDeviceUtilitiesKt.getAllDevicePublicKeys(threadRecipient.getAddress().serialize(), LokiStorageAPI.Companion.getShared()); Set<String> devices = LokiStorageAPI.shared.getAllDevicePublicKeys(threadRecipient.getAddress().serialize());
shouldUpdateInputPanel = devices.contains(recipient.getAddress().serialize()); shouldUpdateInputPanel = devices.contains(recipient.getAddress().serialize());
} else { } else {
shouldUpdateInputPanel = false; shouldUpdateInputPanel = false;
@ -2216,13 +2212,13 @@ 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 = MultiDeviceUtilitiesKt.isFriendsWithAnyLinkedDevice(this, recipient); boolean isFriendsWithAnyLinkedDevices = MultiDeviceUtilities.isFriendsWithAnyLinkedDevice(this, recipient);
boolean shouldEnableInput = isFriendsWithAnyLinkedDevices || !hasPendingFriendRequest; boolean shouldEnableInput = isFriendsWithAnyLinkedDevices || !hasPendingFriendRequest;
updateToggleButtonState(); updateToggleButtonState();
inputPanel.setEnabled(shouldEnableInput); inputPanel.setEnabled(shouldEnableInput);
int hintID = shouldEnableInput ? R.string.activity_conversation_default_hint : R.string.activity_conversation_pending_friend_request_hint; int hintID = shouldEnableInput ? R.string.activity_conversation_default_hint : R.string.activity_conversation_pending_friend_request_hint;
inputPanel.setHint(getResources().getString(hintID)); inputPanel.setHint(getResources().getString(hintID));
if (!shouldEnableInput) { if (shouldEnableInput) {
inputPanel.composeText.requestFocus(); inputPanel.composeText.requestFocus();
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
inputMethodManager.showSoftInput(inputPanel.composeText, 0); inputMethodManager.showSoftInput(inputPanel.composeText, 0);
@ -3050,31 +3046,15 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
public boolean hasPendingFriendRequestWithAnyLinkedDevice() { public boolean hasPendingFriendRequestWithAnyLinkedDevice() {
if (recipient.isGroupRecipient()) return false; if (recipient.isGroupRecipient()) return false;
SettableFuture<Boolean> future = new SettableFuture<>();
LokiStorageAPI storageAPI = LokiStorageAPI.Companion.getShared();
MultiDeviceUtilitiesKt.getAllDeviceFriendRequestStatus(this, recipient.getAddress().serialize(), storageAPI).success(map -> { Map<String, LokiThreadFriendRequestStatus> map = MultiDeviceUtilities.getAllDeviceFriendRequestStatuses(this, recipient.getAddress().serialize());
for (LokiThreadFriendRequestStatus status : map.values()) { for (LokiThreadFriendRequestStatus status : map.values()) {
// Break out of the loop as soon as one of the device has a pending friend request if (status == LokiThreadFriendRequestStatus.REQUEST_SENDING || status == LokiThreadFriendRequestStatus.REQUEST_SENT || status == LokiThreadFriendRequestStatus.REQUEST_RECEIVED) {
if (status == LokiThreadFriendRequestStatus.REQUEST_SENDING || status == LokiThreadFriendRequestStatus.REQUEST_SENT || status == LokiThreadFriendRequestStatus.REQUEST_RECEIVED) { return true;
future.set(true);
break;
}
} }
// If we reached this and we haven't set anything on the future then it means that we don't have a pending request
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;
} }
return false;
} }
// endregion // endregion
} }

View File

@ -61,7 +61,7 @@ public class Address implements Parcelable, Comparable<Address> {
private Address(@NonNull String address, Boolean isPublicChat) { private Address(@NonNull String address, Boolean isPublicChat) {
if (address == null) throw new AssertionError(address); if (address == null) throw new AssertionError(address);
this.address = address; this.address = address.toLowerCase();
this.isPublicChat = isPublicChat; this.isPublicChat = isPublicChat;
} }

View File

@ -72,7 +72,7 @@ import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
import org.thoughtcrime.securesms.loki.LokiPreKeyBundleDatabase; import org.thoughtcrime.securesms.loki.LokiPreKeyBundleDatabase;
import org.thoughtcrime.securesms.loki.LokiPreKeyRecordDatabase; import org.thoughtcrime.securesms.loki.LokiPreKeyRecordDatabase;
import org.thoughtcrime.securesms.loki.LokiThreadDatabase; import org.thoughtcrime.securesms.loki.LokiThreadDatabase;
import org.thoughtcrime.securesms.loki.MultiDeviceUtilitiesKt; import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
import org.thoughtcrime.securesms.mms.IncomingMediaMessage; import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
import org.thoughtcrime.securesms.mms.MmsException; import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage; import org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage;
@ -780,11 +780,6 @@ 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 {
@ -828,8 +823,8 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
} }
private long handleSynchronizeSentExpirationUpdate(@NonNull SentTranscriptMessage message) throws MmsException { private long handleSynchronizeSentExpirationUpdate(@NonNull SentTranscriptMessage message) throws MmsException {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context); MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
Recipient recipient = getSyncMessagePrimaryDestination(message); Recipient recipient = getSyncMessagePrimaryDestination(message);
OutgoingExpirationUpdateMessage expirationUpdateMessage = new OutgoingExpirationUpdateMessage(recipient, OutgoingExpirationUpdateMessage expirationUpdateMessage = new OutgoingExpirationUpdateMessage(recipient,
message.getTimestamp(), message.getTimestamp(),
@ -1099,7 +1094,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
String primaryDevice = MultiDeviceUtilitiesKt.getPrimaryDevicePublicKey(pubKey); String primaryDevice = LokiStorageAPI.shared.getPrimaryDevicePublicKey(pubKey);
long primaryDeviceThreadID = primaryDevice == null ? threadID : DatabaseFactory.getThreadDatabase(context).getThreadIdFor(Recipient.from(context, Address.fromSerialized(primaryDevice), false)); long primaryDeviceThreadID = primaryDevice == null ? threadID : DatabaseFactory.getThreadDatabase(context).getThreadIdFor(Recipient.from(context, Address.fromSerialized(primaryDevice), false));
FriendRequestHandler.updateLastFriendRequestMessage(context, primaryDeviceThreadID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED); FriendRequestHandler.updateLastFriendRequestMessage(context, primaryDeviceThreadID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED);
} }
@ -1107,7 +1102,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
private void updateFriendRequestStatusIfNeeded(@NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) { private void updateFriendRequestStatusIfNeeded(@NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) {
if (!envelope.isFriendRequest()) { return; } if (!envelope.isFriendRequest()) { return; }
// This handles the case where another user sends us a regular message without authorisation // This handles the case where another user sends us a regular message without authorisation
boolean shouldBecomeFriends = MultiDeviceUtilitiesKt.shouldAutomaticallyBecomeFriendsWithDevice(content.getSender(), context); boolean shouldBecomeFriends = MultiDeviceUtilities.shouldAutomaticallyBecomeFriendsWithDevice(content.getSender(), context);
if (shouldBecomeFriends) { if (shouldBecomeFriends) {
// Become friends AND update the message they sent // Become friends AND update the message they sent
becomeFriendsWithContact(content.getSender()); becomeFriendsWithContact(content.getSender());
@ -1536,26 +1531,15 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
} }
private Recipient getPrimaryDeviceRecipient(String recipient) { private Recipient getPrimaryDeviceRecipient(String recipient) {
SettableFuture<String> device = new SettableFuture<>(); try {
String primaryDevice = LokiStorageAPI.shared.getPrimaryDevicePublicKey(recipient);
// Get the primary device
LokiStorageAPI.shared.getPrimaryDevicePublicKey(recipient).success(primaryDevice -> {
String publicKey = (primaryDevice != null) ? primaryDevice : recipient; String publicKey = (primaryDevice != null) ? primaryDevice : recipient;
// If our the public key matches our primary device then we need to forward the message to ourselves (Note to self) // If the public key matches our primary device then we need to forward the message to ourselves (Note to self)
String ourPrimaryDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(context); String ourPrimaryDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
if (ourPrimaryDevice != null && ourPrimaryDevice.equals(publicKey)) { if (ourPrimaryDevice != null && ourPrimaryDevice.equals(publicKey)) {
publicKey = TextSecurePreferences.getLocalNumber(context); publicKey = TextSecurePreferences.getLocalNumber(context);
} }
device.set(publicKey); return Recipient.from(context, Address.fromSerialized(publicKey), false);
return Unit.INSTANCE;
}).fail(exception -> {
device.set(recipient);
return Unit.INSTANCE;
});
try {
String primarySender = device.get();
return Recipient.from(context, Address.fromSerialized(primarySender), false);
} catch (Exception e) { } catch (Exception e) {
Log.d("Loki", "Failed to get primary device public key for message. " + e.getMessage()); Log.d("Loki", "Failed to get primary device public key for message. " + e.getMessage());
return Recipient.from(context, Address.fromSerialized(recipient), false); return Recipient.from(context, Address.fromSerialized(recipient), false);
@ -1610,7 +1594,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
return sender.isBlocked(); return sender.isBlocked();
} else if (content.getSyncMessage().isPresent()) { } else if (content.getSyncMessage().isPresent()) {
// We should ignore a sync message if the sender is not one of our devices // We should ignore a sync message if the sender is not one of our devices
boolean isOurDevice = MultiDeviceUtilitiesKt.isOneOfOurDevices(context, sender.getAddress()); boolean isOurDevice = MultiDeviceUtilities.isOneOfOurDevices(context, sender.getAddress());
if (!isOurDevice) { Log.w(TAG, "Got a sync message from a device that is not ours!."); } if (!isOurDevice) { Log.w(TAG, "Got a sync message from a device that is not ours!."); }
return !isOurDevice; return !isOurDevice;
} }

View File

@ -22,7 +22,7 @@ import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.JobManager; import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.loki.MultiDeviceUtilitiesKt; import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
import org.thoughtcrime.securesms.mms.MmsException; import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage; import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
@ -43,6 +43,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSy
import org.whispersystems.signalservice.api.messages.shared.SharedContact; import org.whispersystems.signalservice.api.messages.shared.SharedContact;
import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException; import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
import org.whispersystems.signalservice.loki.messaging.LokiSyncMessage; import org.whispersystems.signalservice.loki.messaging.LokiSyncMessage;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -280,7 +281,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
LokiSyncMessage syncMessage = null; LokiSyncMessage syncMessage = null;
if (shouldSendSyncMessage) { if (shouldSendSyncMessage) {
// Set the sync message destination the primary device, this way it will show that we sent a message to the primary device and not a secondary device // Set the sync message destination the primary device, this way it will show that we sent a message to the primary device and not a secondary device
String primaryDevice = MultiDeviceUtilitiesKt.getPrimaryDevicePublicKey(address.getNumber()); String primaryDevice = LokiStorageAPI.shared.getPrimaryDevicePublicKey(address.getNumber());
SignalServiceAddress primaryAddress = primaryDevice == null ? address : new SignalServiceAddress(primaryDevice); SignalServiceAddress primaryAddress = primaryDevice == null ? address : new SignalServiceAddress(primaryDevice);
// We also need to use the original message id and not -1 // We also need to use the original message id and not -1
syncMessage = new LokiSyncMessage(primaryAddress, templateMessageId); syncMessage = new LokiSyncMessage(primaryAddress, templateMessageId);

View File

@ -14,7 +14,7 @@ import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.dependencies.InjectableType; 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.loki.MultiDeviceUtilitiesKt; import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.ExpiringMessageManager; import org.thoughtcrime.securesms.service.ExpiringMessageManager;
@ -30,6 +30,7 @@ import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage; import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException; import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
import org.whispersystems.signalservice.loki.messaging.LokiSyncMessage; import org.whispersystems.signalservice.loki.messaging.LokiSyncMessage;
import java.io.IOException; import java.io.IOException;
@ -231,7 +232,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
LokiSyncMessage syncMessage = null; LokiSyncMessage syncMessage = null;
if (shouldSendSyncMessage) { if (shouldSendSyncMessage) {
// Set the sync message destination to the primary device, this way it will show that we sent a message to the primary device and not a secondary device // Set the sync message destination to the primary device, this way it will show that we sent a message to the primary device and not a secondary device
String primaryDevice = MultiDeviceUtilitiesKt.getPrimaryDevicePublicKey(address.getNumber()); String primaryDevice = LokiStorageAPI.shared.getPrimaryDevicePublicKey(address.getNumber());
SignalServiceAddress primaryAddress = primaryDevice == null ? address : new SignalServiceAddress(primaryDevice); SignalServiceAddress primaryAddress = primaryDevice == null ? address : new SignalServiceAddress(primaryDevice);
// We also need to use the original message id and not -1 // We also need to use the original message id and not -1
syncMessage = new LokiSyncMessage(primaryAddress, templateMessageId); syncMessage = new LokiSyncMessage(primaryAddress, templateMessageId);

View File

@ -10,7 +10,7 @@ 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.MultiDeviceUtilitiesKt; import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
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;
@ -98,7 +98,7 @@ public class TypingSendJob extends BaseJob implements InjectableType {
SignalServiceTypingMessage typingMessage = new SignalServiceTypingMessage(typing ? Action.STARTED : Action.STOPPED, System.currentTimeMillis(), groupId); SignalServiceTypingMessage typingMessage = new SignalServiceTypingMessage(typing ? Action.STARTED : Action.STOPPED, System.currentTimeMillis(), groupId);
// Loki - Don't send typing indicators in group chats or to ourselves // Loki - Don't send typing indicators in group chats or to ourselves
if (!recipient.isGroupRecipient() && !MultiDeviceUtilitiesKt.isOneOfOurDevices(context, recipient.getAddress())) { if (!recipient.isGroupRecipient() && !MultiDeviceUtilities.isOneOfOurDevices(context, recipient.getAddress())) {
messageSender.sendTyping(0, addresses, unidentifiedAccess, typingMessage); messageSender.sendTyping(0, addresses, unidentifiedAccess, typingMessage);
} }
} }

View File

@ -1,11 +1,9 @@
@file:JvmName("MultiDeviceUtilities")
package org.thoughtcrime.securesms.loki package org.thoughtcrime.securesms.loki
import android.content.Context import android.content.Context
import android.os.Handler import android.os.Handler
import nl.komponents.kovenant.Promise import nl.komponents.kovenant.Promise
import nl.komponents.kovenant.deferred
import nl.komponents.kovenant.functional.bind
import nl.komponents.kovenant.functional.map
import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.database.Address import org.thoughtcrime.securesms.database.Address
@ -13,7 +11,6 @@ import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.logging.Log import org.thoughtcrime.securesms.logging.Log
import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.thoughtcrime.securesms.util.concurrent.SettableFuture
import org.whispersystems.libsignal.util.guava.Optional import org.whispersystems.libsignal.util.guava.Optional
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
@ -23,85 +20,53 @@ import org.whispersystems.signalservice.loki.api.PairingAuthorisation
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus
import org.whispersystems.signalservice.loki.utilities.retryIfNeeded import org.whispersystems.signalservice.loki.utilities.retryIfNeeded
fun getAllDeviceFriendRequestStatus(context: Context, hexEncodedPublicKey: String, storageAPI: LokiStorageAPI): Promise<Map<String, LokiThreadFriendRequestStatus>, Exception> { fun getAllDeviceFriendRequestStatuses(context: Context, hexEncodedPublicKey: String): Map<String, LokiThreadFriendRequestStatus> {
val lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context) val lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context)
return storageAPI.getAllDevicePublicKeys(hexEncodedPublicKey).map { keys -> val keys = LokiStorageAPI.shared.getAllDevicePublicKeys(hexEncodedPublicKey)
val map = mutableMapOf<String, LokiThreadFriendRequestStatus>() val map = mutableMapOf<String, LokiThreadFriendRequestStatus>()
for (devicePublicKey in keys) {
for (devicePublicKey in keys) { val device = Recipient.from(context, Address.fromSerialized(devicePublicKey), false)
val device = Recipient.from(context, Address.fromSerialized(devicePublicKey), false) val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(device)
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(device) val friendRequestStatus = if (threadID < 0) LokiThreadFriendRequestStatus.NONE else lokiThreadDatabase.getFriendRequestStatus(threadID)
val friendRequestStatus = if (threadID < 0) LokiThreadFriendRequestStatus.NONE else lokiThreadDatabase.getFriendRequestStatus(threadID) map[devicePublicKey] = friendRequestStatus
map.put(devicePublicKey, friendRequestStatus);
}
map
} }
return map
} }
fun getAllDevicePublicKeys(context: Context, hexEncodedPublicKey: String, storageAPI: LokiStorageAPI, block: (devicePublicKey: String, isFriend: Boolean, friendCount: Int) -> Unit) { fun getAllDevicePublicKeysWithFriendStatus(context: Context, hexEncodedPublicKey: String): Map<String, Boolean> {
val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context) val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context)
val devices = getAllDevicePublicKeys(hexEncodedPublicKey, storageAPI).toMutableSet() val devices = LokiStorageAPI.shared.getAllDevicePublicKeys(hexEncodedPublicKey).toMutableSet()
if (hexEncodedPublicKey != userHexEncodedPublicKey) { if (hexEncodedPublicKey != userHexEncodedPublicKey) {
devices.remove(userHexEncodedPublicKey) devices.remove(userHexEncodedPublicKey)
} }
val friends = getFriendPublicKeys(context, devices) val friends = getFriendPublicKeys(context, devices)
val map = mutableMapOf<String, Boolean>()
for (device in devices) { for (device in devices) {
block(device, friends.contains(device), friends.count()) map[device] = friends.contains(device)
} }
return map
} }
fun getAllDevicePublicKeys(hexEncodedPublicKey: String, storageAPI: LokiStorageAPI): Set<String> { fun getFriendCount(context: Context, devices: Set<String>): Int {
val future = SettableFuture<Set<String>>() return getFriendPublicKeys(context, devices).count()
storageAPI.getAllDevicePublicKeys(hexEncodedPublicKey).success { future.set(it) }.fail { future.setException(it) }
return try {
future.get()
} catch (e: Exception) {
setOf()
}
} }
fun shouldAutomaticallyBecomeFriendsWithDevice(publicKey: String, context: Context): Boolean { fun shouldAutomaticallyBecomeFriendsWithDevice(publicKey: String, context: Context): Boolean {
val lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context) val lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context)
val storageAPI = LokiStorageAPI.shared val storageAPI = LokiStorageAPI.shared
val future = SettableFuture<Boolean>()
storageAPI.getPrimaryDevicePublicKey(publicKey).success { primaryDevicePublicKey -> // If the public key doesn't have any other devices then go through regular friend request logic
if (primaryDevicePublicKey == null) { val primaryDevicePublicKey = storageAPI.getPrimaryDevicePublicKey(publicKey) ?: return false
// If the public key doesn't have any other devices then go through regular friend request logic
future.set(false) // If this is one of our devices then we should become friends
return@success if (isOneOfOurDevices(context, publicKey)) {
} return true
// If we are the primary device and the public key is our secondary device then we should become friends
val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context)
if (primaryDevicePublicKey == userHexEncodedPublicKey) {
storageAPI.getSecondaryDevicePublicKeys(userHexEncodedPublicKey).success { secondaryDevices ->
future.set(secondaryDevices.contains(publicKey))
}.fail {
future.set(false)
}
return@success
}
// If we share the same primary device then we should become friends
val ourPrimaryDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(context)
if (ourPrimaryDevice != null && ourPrimaryDevice == primaryDevicePublicKey) {
future.set(true)
return@success
}
// If we are friends with the primary device then we should become friends
val primaryDevice = Recipient.from(context, Address.fromSerialized(primaryDevicePublicKey), false)
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(primaryDevice)
if (threadID < 0) {
future.set(false)
return@success
}
future.set(lokiThreadDatabase.getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS)
} }
return try { // If we are friends with the primary device then we should become friends
future.get() val primaryDevice = Recipient.from(context, Address.fromSerialized(primaryDevicePublicKey), false)
} catch (e: Exception) { val primaryDeviceThreadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(primaryDevice)
false return primaryDeviceThreadID >= 0 && lokiThreadDatabase.getFriendRequestStatus(primaryDeviceThreadID) == LokiThreadFriendRequestStatus.FRIENDS
}
} }
fun sendPairingAuthorisationMessage(context: Context, contactHexEncodedPublicKey: String, authorisation: PairingAuthorisation): Promise<Unit, Exception> { fun sendPairingAuthorisationMessage(context: Context, contactHexEncodedPublicKey: String, authorisation: PairingAuthorisation): Promise<Unit, Exception> {
@ -157,27 +122,12 @@ fun shouldSendSycMessage(context: Context, address: Address): Boolean {
return false return false
} }
// Don't send sync messages if it's our address // Don't send sync messages if it's one of our devices
val publicKey = address.serialize() return !isOneOfOurDevices(context, address)
if (publicKey == TextSecurePreferences.getLocalNumber(context)) { }
return false
}
val storageAPI = LokiStorageAPI.shared fun isOneOfOurDevices(context: Context, publicKey: String): Boolean {
val future = SettableFuture<Boolean>() return isOneOfOurDevices(context, Address.fromSerialized(publicKey))
storageAPI.getPrimaryDevicePublicKey(publicKey).success { primaryDevicePublicKey ->
val isOurPrimaryDevice = primaryDevicePublicKey != null && TextSecurePreferences.getMasterHexEncodedPublicKey(context) == publicKey
// Don't send sync message if the primary device is the same as ours
future.set(!isOurPrimaryDevice)
}.fail {
future.set(false)
}
return try {
future.get()
} catch (e: Exception) {
false
}
} }
fun isOneOfOurDevices(context: Context, address: Address): Boolean { fun isOneOfOurDevices(context: Context, address: Address): Boolean {
@ -186,61 +136,18 @@ fun isOneOfOurDevices(context: Context, address: Address): Boolean {
} }
val ourPublicKey = TextSecurePreferences.getLocalNumber(context) val ourPublicKey = TextSecurePreferences.getLocalNumber(context)
val storageAPI = LokiStorageAPI.shared val devices = LokiStorageAPI.shared.getAllDevicePublicKeys(ourPublicKey)
val future = SettableFuture<Boolean>() return devices.contains(address.serialize())
storageAPI.getAllDevicePublicKeys(ourPublicKey).success {
future.set(it.contains(address.serialize()))
}.fail {
future.set(false)
}
return try {
future.get()
} catch (e: Exception) {
false
}
}
fun getPrimaryDevicePublicKey(hexEncodedPublicKey: String): String? {
val storageAPI = LokiStorageAPI.shared
val future = SettableFuture<String?>()
storageAPI.getPrimaryDevicePublicKey(hexEncodedPublicKey).success {
future.set(it)
}.fail {
future.set(null)
}
return try {
future.get()
} catch (e: Exception) {
null
}
} }
fun isFriendsWithAnyLinkedDevice(context: Context, recipient: Recipient): Boolean { fun isFriendsWithAnyLinkedDevice(context: Context, recipient: Recipient): Boolean {
if (recipient.isGroupRecipient) return true if (recipient.isGroupRecipient) return true
val future = SettableFuture<Boolean>()
val storageAPI = LokiStorageAPI.shared
getAllDeviceFriendRequestStatus(context, recipient.address.serialize(), storageAPI).success { map -> val map = getAllDeviceFriendRequestStatuses(context, recipient.address.serialize())
for (status in map.values) { for (status in map.values) {
if (status == LokiThreadFriendRequestStatus.FRIENDS) { if (status == LokiThreadFriendRequestStatus.FRIENDS) {
future.set(true) return true
break
}
} }
if (!future.isDone) {
future.set(false)
}
}.fail { e ->
future.set(false)
} }
return false
try {
return future.get()
} catch (e: Exception) {
return false
}
} }

View File

@ -20,7 +20,7 @@ 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.MultiDeviceUtilitiesKt; import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
import org.thoughtcrime.securesms.service.ExpiringMessageManager; import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.whispersystems.signalservice.loki.api.LokiStorageAPI; import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
@ -90,17 +90,17 @@ public class MarkReadReceiver extends BroadcastReceiver {
.collect(Collectors.groupingBy(SyncMessageId::getAddress)); .collect(Collectors.groupingBy(SyncMessageId::getAddress));
for (Address address : addressMap.keySet()) { for (Address address : addressMap.keySet()) {
LokiStorageAPI storageAPI = LokiStorageAPI.Companion.getShared();
List<Long> timestamps = Stream.of(addressMap.get(address)).map(SyncMessageId::getTimetamp).toList(); List<Long> timestamps = Stream.of(addressMap.get(address)).map(SyncMessageId::getTimetamp).toList();
MultiDeviceUtilitiesKt.getAllDevicePublicKeys(context, address.serialize(), storageAPI, (devicePublicKey, isFriend, friendCount) -> { Map<String, Boolean> devices = MultiDeviceUtilities.getAllDevicePublicKeysWithFriendStatus(context, address.serialize());
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 // Loki - This also prevents read receipts from being sent in group chats as they don't maintain a friend request status
if (isFriend) { if (isFriend) {
ApplicationContext.getInstance(context).getJobManager().add(new SendReadReceiptJob(Address.fromSerialized(devicePublicKey), timestamps)); ApplicationContext.getInstance(context).getJobManager().add(new SendReadReceiptJob(Address.fromSerialized(device), timestamps));
} }
return Unit.INSTANCE; }
});
} }
} }

View File

@ -44,7 +44,7 @@ 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.FriendRequestHandler;
import org.thoughtcrime.securesms.loki.GeneralUtilitiesKt; import org.thoughtcrime.securesms.loki.GeneralUtilitiesKt;
import org.thoughtcrime.securesms.loki.MultiDeviceUtilitiesKt; import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
import org.thoughtcrime.securesms.loki.PushMessageSyncSendJob; import org.thoughtcrime.securesms.loki.PushMessageSyncSendJob;
import org.thoughtcrime.securesms.mms.MmsException; import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage; import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
@ -63,6 +63,8 @@ import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus; import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus;
import java.io.IOException; import java.io.IOException;
import java.util.Map;
import java.util.Set;
import kotlin.Unit; import kotlin.Unit;
@ -75,24 +77,20 @@ public class MessageSender {
sendBackgroundMessage(context, contactHexEncodedPublicKey); sendBackgroundMessage(context, contactHexEncodedPublicKey);
// Go through the other devices and only send background messages if we're friends or we have received friend request // Go through the other devices and only send background messages if we're friends or we have received friend request
LokiStorageAPI storageAPI = LokiStorageAPI.Companion.getShared(); Set<String> devices = LokiStorageAPI.shared.getAllDevicePublicKeys(contactHexEncodedPublicKey);
storageAPI.getAllDevicePublicKeys(contactHexEncodedPublicKey).success(devices -> { for (String device : devices) {
for (String device : devices) { // Don't send message to the device we already have sent to
// Don't send message to the device we already have sent to if (device.equals(contactHexEncodedPublicKey)) { continue; }
if (device.equals(contactHexEncodedPublicKey)) { continue; } Recipient recipient = Recipient.from(context, Address.fromSerialized(device), false);
Recipient recipient = Recipient.from(context, Address.fromSerialized(device), false); long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(recipient);
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(recipient); if (threadID < 0) { continue; }
if (threadID < 0) { continue; } LokiThreadFriendRequestStatus friendRequestStatus = DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID);
LokiThreadFriendRequestStatus friendRequestStatus = DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID); if (friendRequestStatus == LokiThreadFriendRequestStatus.FRIENDS || friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_RECEIVED) {
if (friendRequestStatus == LokiThreadFriendRequestStatus.FRIENDS || friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_RECEIVED) { sendBackgroundMessage(context, device);
sendBackgroundMessage(context, device);
}
// TODO: Do we want to send a custom FR Message if we're not friends and we haven't received a friend request?
} }
return Unit.INSTANCE; // TODO: Do we want to send a custom FR Message if we're not friends and we haven't received a friend request?
}); }
} }
public static void sendBackgroundMessage(Context context, String contactHexEncodedPublicKey) { public static void sendBackgroundMessage(Context context, String contactHexEncodedPublicKey) {
@ -198,20 +196,16 @@ public class MessageSender {
final byte[] message, final byte[] message,
final int ttl) { final int ttl) {
String ourPublicKey = TextSecurePreferences.getLocalNumber(context); String ourPublicKey = TextSecurePreferences.getLocalNumber(context);
LokiStorageAPI storageAPI = LokiStorageAPI.Companion.getShared();
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager(); JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
Set<String> devices = LokiStorageAPI.shared.getAllDevicePublicKeys(ourPublicKey);
for (String device : devices) {
// Don't send to ourselves
if (device.equals(ourPublicKey)) { continue; }
storageAPI.getAllDevicePublicKeys(ourPublicKey).success(devices -> { // Create a send job for our device
for (String device : devices) { Address address = Address.fromSerialized(device);
// Don't send to ourselves jobManager.add(new PushMessageSyncSendJob(messageID, address, timestamp, message, ttl));
if (device.equals(ourPublicKey)) { continue; } }
// Create a send job for our device
Address address = Address.fromSerialized(device);
jobManager.add(new PushMessageSyncSendJob(messageID, address, timestamp, message, ttl));
}
return Unit.INSTANCE;
});
} }
public static void resendGroupMessage(Context context, MessageRecord messageRecord, Address filterAddress) { public static void resendGroupMessage(Context context, MessageRecord messageRecord, Address filterAddress) {
@ -260,7 +254,6 @@ public class MessageSender {
} }
private static void sendTextPush(Context context, Recipient recipient, long messageId) { private static void sendTextPush(Context context, Recipient recipient, long messageId) {
LokiStorageAPI storageAPI = LokiStorageAPI.Companion.getShared();
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager(); 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
@ -271,39 +264,40 @@ public class MessageSender {
} }
// Note to self // Note to self
boolean isNoteToSelf = MultiDeviceUtilitiesKt.isOneOfOurDevices(context, recipient.getAddress()); boolean isNoteToSelf = MultiDeviceUtilities.isOneOfOurDevices(context, recipient.getAddress());
if (isNoteToSelf) { if (isNoteToSelf) {
jobManager.add(new PushTextSendJob(messageId, recipient.getAddress())); jobManager.add(new PushTextSendJob(messageId, recipient.getAddress()));
return; return;
} }
boolean[] hasSentSyncMessage = { false }; boolean hasSentSyncMessage = false;
MultiDeviceUtilitiesKt.getAllDevicePublicKeys(context, recipientPublicKey, storageAPI, (devicePublicKey, isFriend, friendCount) -> { Map<String, Boolean> devices = MultiDeviceUtilities.getAllDevicePublicKeysWithFriendStatus(context, recipientPublicKey);
Util.runOnMain(() -> { int friendCount = MultiDeviceUtilities.getFriendCount(context, devices.keySet());
Address address = Address.fromSerialized(devicePublicKey); for (Map.Entry<String, Boolean> entry : devices.entrySet()) {
long messageIDToUse = recipientPublicKey.equals(devicePublicKey) ? messageId : -1L; String devicePublicKey = entry.getKey();
boolean isFriend = entry.getValue();
if (isFriend) { Address address = Address.fromSerialized(devicePublicKey);
// Send a normal message if the user is friends with the recipient long messageIDToUse = recipientPublicKey.equals(devicePublicKey) ? messageId : -1L;
// We should also send a sync message if we haven't already sent one
boolean shouldSendSyncMessage = !hasSentSyncMessage[0] && MultiDeviceUtilitiesKt.shouldSendSycMessage(context, address); if (isFriend) {
jobManager.add(new PushTextSendJob(messageId, messageIDToUse, address, shouldSendSyncMessage)); // Send a normal message if the user is friends with the recipient
hasSentSyncMessage[0] = shouldSendSyncMessage; // We should also send a sync message if we haven't already sent one
} else { boolean shouldSendSyncMessage = !hasSentSyncMessage && MultiDeviceUtilities.shouldSendSycMessage(context, address);
// Send friend requests to non friends. If the user is friends with any jobManager.add(new PushTextSendJob(messageId, messageIDToUse, address, shouldSendSyncMessage));
// of the devices then send out a default friend request message. hasSentSyncMessage = shouldSendSyncMessage;
boolean isFriendsWithAny = (friendCount > 0); } else {
String defaultFriendRequestMessage = isFriendsWithAny ? "Accept this friend request to enable messages to be synced across devices" : null; // Send friend requests to non friends. If the user is friends with any
jobManager.add(new PushTextSendJob(messageId, messageIDToUse, address, true, defaultFriendRequestMessage, false)); // 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;
return Unit.INSTANCE; jobManager.add(new PushTextSendJob(messageId, messageIDToUse, address, true, defaultFriendRequestMessage, false));
}); }
}
} }
private static void sendMediaPush(Context context, Recipient recipient, long messageId) { private static void sendMediaPush(Context context, Recipient recipient, long messageId) {
LokiStorageAPI storageAPI = LokiStorageAPI.Companion.getShared();
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager(); 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
@ -314,36 +308,37 @@ public class MessageSender {
} }
// Note to self // Note to self
boolean isNoteToSelf = MultiDeviceUtilitiesKt.isOneOfOurDevices(context, recipient.getAddress()); boolean isNoteToSelf = MultiDeviceUtilities.isOneOfOurDevices(context, recipient.getAddress());
if (isNoteToSelf) { if (isNoteToSelf) {
jobManager.add(new PushTextSendJob(messageId, recipient.getAddress())); jobManager.add(new PushTextSendJob(messageId, recipient.getAddress()));
return; return;
} }
boolean[] hasSentSyncMessage = { false }; boolean hasSentSyncMessage = false;
MultiDeviceUtilitiesKt.getAllDevicePublicKeys(context, recipientPublicKey, storageAPI, (devicePublicKey, isFriend, friendCount) -> { Map<String, Boolean> devices = MultiDeviceUtilities.getAllDevicePublicKeysWithFriendStatus(context, recipientPublicKey);
Util.runOnMain(() -> { int friendCount = MultiDeviceUtilities.getFriendCount(context, devices.keySet());
Address address = Address.fromSerialized(devicePublicKey); for (Map.Entry<String, Boolean> entry : devices.entrySet()) {
long messageIDToUse = recipientPublicKey.equals(devicePublicKey) ? messageId : -1L; String devicePublicKey = entry.getKey();
boolean isFriend = entry.getValue();
if (isFriend) { Address address = Address.fromSerialized(devicePublicKey);
// Send a normal message if the user is friends with the recipient long messageIDToUse = recipientPublicKey.equals(devicePublicKey) ? messageId : -1L;
// We should also send a sync message if we haven't already sent one
boolean shouldSendSyncMessage = !hasSentSyncMessage[0] && MultiDeviceUtilitiesKt.shouldSendSycMessage(context, address);
PushMediaSendJob.enqueue(context, jobManager, messageId, messageIDToUse, address, 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;
PushMediaSendJob.enqueue(context, jobManager, messageId, messageIDToUse, address, true, defaultFriendRequestMessage, false);
}
});
return Unit.INSTANCE;
});
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);
}
}
} }
private static void sendGroupPush(Context context, Recipient recipient, long messageId, Address filterAddress) { private static void sendGroupPush(Context context, Recipient recipient, long messageId, Address filterAddress) {