clean up V1 multi device

This commit is contained in:
Ryan ZHAO 2021-02-17 12:27:00 +11:00
parent 37cb4cd28c
commit 7a17b5769a
9 changed files with 53 additions and 156 deletions

View File

@ -115,8 +115,6 @@ import org.session.libsignal.service.loki.protocol.mentions.MentionsManager;
import org.session.libsignal.service.loki.protocol.meta.SessionMetaProtocol; import org.session.libsignal.service.loki.protocol.meta.SessionMetaProtocol;
import org.session.libsignal.service.loki.protocol.sessionmanagement.SessionManagementProtocol; import org.session.libsignal.service.loki.protocol.sessionmanagement.SessionManagementProtocol;
import org.session.libsignal.service.loki.protocol.sessionmanagement.SessionManagementProtocolDelegate; import org.session.libsignal.service.loki.protocol.sessionmanagement.SessionManagementProtocolDelegate;
import org.session.libsignal.service.loki.protocol.shelved.multidevice.DeviceLink;
import org.session.libsignal.service.loki.protocol.shelved.syncmessages.SyncMessagesProtocol;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -204,18 +202,11 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster); SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB); MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB);
SessionMetaProtocol.Companion.configureIfNeeded(apiDB, userPublicKey); SessionMetaProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
SyncMessagesProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
} }
org.session.libsignal.service.loki.protocol.shelved.multidevice.MultiDeviceProtocol.Companion.configureIfNeeded(apiDB);
SessionManagementProtocol.Companion.configureIfNeeded(sessionResetImpl, sskDatabase, this); SessionManagementProtocol.Companion.configureIfNeeded(sessionResetImpl, sskDatabase, this);
setUpP2PAPIIfNeeded(); setUpP2PAPIIfNeeded();
PushNotificationAPI.Companion.configureIfNeeded(BuildConfig.DEBUG); PushNotificationAPI.Companion.configureIfNeeded(BuildConfig.DEBUG);
if (setUpStorageAPIIfNeeded()) { setUpStorageAPIIfNeeded();
if (userPublicKey != null) {
Set<DeviceLink> deviceLinks = DatabaseFactory.getLokiAPIDatabase(this).getDeviceLinks(userPublicKey);
FileServerAPI.shared.setDeviceLinks(deviceLinks);
}
}
resubmitProfilePictureIfNeeded(); resubmitProfilePictureIfNeeded();
publicChatManager = new PublicChatManager(this); publicChatManager = new PublicChatManager(this);
updateOpenGroupProfilePicturesIfNeeded(); updateOpenGroupProfilePicturesIfNeeded();

View File

@ -12,7 +12,6 @@ import org.thoughtcrime.securesms.jobs.TypingSendJob;
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol; import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol;
import org.session.libsession.messaging.threads.recipients.Recipient; import org.session.libsession.messaging.threads.recipients.Recipient;
import org.session.libsession.utilities.Util; import org.session.libsession.utilities.Util;
import org.session.libsignal.service.loki.protocol.shelved.multidevice.MultiDeviceProtocol;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -87,12 +86,8 @@ public class TypingStatusSender {
if (recipient != null && !SessionMetaProtocol.shouldSendTypingIndicator(recipient.getAddress())) { return; } if (recipient != null && !SessionMetaProtocol.shouldSendTypingIndicator(recipient.getAddress())) { return; }
// Loki - Take into account multi device // Loki - Take into account multi device
if (recipient == null) { return; } if (recipient == null) { return; }
Set<String> linkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(recipient.getAddress().serialize()); long threadID = threadDatabase.getOrCreateThreadIdFor(recipient);
for (String device : linkedDevices) { ApplicationContext.getInstance(context).getJobManager().add(new TypingSendJob(threadID, typingStarted));
Recipient deviceAsRecipient = Recipient.from(context, Address.Companion.fromSerialized(device), false);
long deviceThreadID = threadDatabase.getOrCreateThreadIdFor(deviceAsRecipient);
ApplicationContext.getInstance(context).getJobManager().add(new TypingSendJob(deviceThreadID, typingStarted));
}
} }
private class StartRunnable implements Runnable { private class StartRunnable implements Runnable {

View File

@ -92,7 +92,6 @@ import org.session.libsignal.service.loki.api.opengroups.PublicChat;
import org.session.libsignal.service.loki.protocol.mentions.Mention; import org.session.libsignal.service.loki.protocol.mentions.Mention;
import org.session.libsignal.service.loki.protocol.mentions.MentionsManager; import org.session.libsignal.service.loki.protocol.mentions.MentionsManager;
import org.session.libsignal.service.loki.protocol.meta.SessionMetaProtocol; import org.session.libsignal.service.loki.protocol.meta.SessionMetaProtocol;
import org.session.libsignal.service.loki.protocol.shelved.multidevice.MultiDeviceProtocol;
import org.session.libsignal.service.loki.utilities.HexEncodingKt; import org.session.libsignal.service.loki.utilities.HexEncodingKt;
import org.session.libsignal.service.loki.utilities.PublicKeyValidation; import org.session.libsignal.service.loki.utilities.PublicKeyValidation;
import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.ApplicationContext;
@ -2620,10 +2619,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
// region Loki // region Loki
private void updateTitleTextView(Recipient recipient) { private void updateTitleTextView(Recipient recipient) {
String userPublicKey = TextSecurePreferences.getLocalNumber(this); String userPublicKey = TextSecurePreferences.getLocalNumber(this);
Set<String> allUserDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey);
if (recipient == null) { if (recipient == null) {
titleTextView.setText("Compose"); titleTextView.setText("Compose");
} else if (allUserDevices.contains(recipient.getAddress().toString().toLowerCase())) { } else if (recipient.getAddress().toString().toLowerCase() == userPublicKey) {
titleTextView.setText("Note to Self"); titleTextView.setText("Note to Self");
} else { } else {
boolean hasName = (recipient.getName() != null && !recipient.getName().isEmpty()); boolean hasName = (recipient.getName() != null && !recipient.getName().isEmpty());

View File

@ -36,7 +36,6 @@ import org.session.libsignal.service.api.messages.SignalServiceContent;
import org.session.libsignal.service.api.messages.SignalServiceDataMessage; import org.session.libsignal.service.api.messages.SignalServiceDataMessage;
import org.session.libsignal.service.api.messages.SignalServiceGroup; import org.session.libsignal.service.api.messages.SignalServiceGroup;
import org.session.libsignal.service.api.messages.SignalServiceGroup.Type; import org.session.libsignal.service.api.messages.SignalServiceGroup.Type;
import org.session.libsignal.service.loki.protocol.shelved.multidevice.MultiDeviceProtocol;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
@ -141,9 +140,7 @@ public class GroupMessageProcessor {
if (group.getGroupType() == SignalServiceGroup.GroupType.SIGNAL) { if (group.getGroupType() == SignalServiceGroup.GroupType.SIGNAL) {
// Loki - Only update the group if the group admin sent the message // Loki - Only update the group if the group admin sent the message
String masterDevice = MultiDeviceProtocol.shared.getMasterDevice(content.getSender()); if (!groupRecord.getAdmins().contains(Address.Companion.fromSerialized(content.getSender()))) {
if (masterDevice == null) { masterDevice = content.getSender(); }
if (!groupRecord.getAdmins().contains(Address.Companion.fromSerialized(masterDevice))) {
Log.d("Loki", "Received a group update message from a non-admin user for: " + id +"; ignoring."); Log.d("Loki", "Received a group update message from a non-admin user for: " + id +"; ignoring.");
return null; return null;
} }
@ -219,9 +216,7 @@ public class GroupMessageProcessor {
@NonNull SignalServiceGroup group, @NonNull SignalServiceGroup group,
@NonNull GroupRecord record) @NonNull GroupRecord record)
{ {
String masterDevice = MultiDeviceProtocol.shared.getMasterDevice(content.getSender()); if (record.getMembers().contains(Address.Companion.fromSerialized(content.getSender()))) {
if (masterDevice == null) { masterDevice = content.getSender(); }
if (record.getMembers().contains(Address.Companion.fromSerialized(masterDevice))) {
ApplicationContext.getInstance(context) ApplicationContext.getInstance(context)
.getJobManager() .getJobManager()
.add(new PushGroupUpdateJob(content.getSender(), group.getGroupId())); .add(new PushGroupUpdateJob(content.getSender(), group.getGroupId()));
@ -242,10 +237,8 @@ public class GroupMessageProcessor {
GroupContext.Builder builder = createGroupContext(group); GroupContext.Builder builder = createGroupContext(group);
builder.setType(GroupContext.Type.QUIT); builder.setType(GroupContext.Type.QUIT);
String masterDevice = MultiDeviceProtocol.shared.getMasterDevice(content.getSender()); if (members.contains(Address.Companion.fromExternal(context, content.getSender()))) {
if (masterDevice == null) { masterDevice = content.getSender(); } database.removeMember(id, Address.Companion.fromExternal(context, content.getSender()));
if (members.contains(Address.Companion.fromExternal(context, masterDevice))) {
database.removeMember(id, Address.Companion.fromExternal(context, masterDevice));
if (outgoing) database.setActive(id, false); if (outgoing) database.setActive(id, false);
return storeMessage(context, content, group, builder.build(), outgoing); return storeMessage(context, content, group, builder.build(), outgoing);

View File

@ -269,54 +269,34 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
SignalServiceDataMessage message = content.getDataMessage().get(); SignalServiceDataMessage message = content.getDataMessage().get();
boolean isMediaMessage = message.getAttachments().isPresent() || message.getQuote().isPresent() || message.getSharedContacts().isPresent() || message.getPreviews().isPresent() || message.getSticker().isPresent(); boolean isMediaMessage = message.getAttachments().isPresent() || message.getQuote().isPresent() || message.getSharedContacts().isPresent() || message.getPreviews().isPresent() || message.getSticker().isPresent();
if (message.isDeviceUnlinkingRequest()) { if (message.getClosedGroupUpdateV2().isPresent()) {
throw new UnsupportedOperationException("Device link operations are not supported!"); ClosedGroupsProtocolV2.handleMessage(context, message.getClosedGroupUpdateV2().get(), message.getTimestamp(), envelope.getSource(), content.getSender());
} else { }
if (message.isEndSession()) {
handleEndSessionMessage(content, smsMessageId);
} else if (message.isGroupUpdate()) {
handleGroupMessage(content, message, smsMessageId);
} else if (message.isExpirationUpdate()) {
handleExpirationUpdate(content, message, smsMessageId);
} else if (isMediaMessage) {
handleMediaMessage(content, message, smsMessageId, Optional.absent());
} else if (message.getBody().isPresent()) {
handleTextMessage(content, message, smsMessageId, Optional.absent());
}
if (message.getClosedGroupUpdateV2().isPresent()) { if (message.getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getGroupInfo().get()))) {
ClosedGroupsProtocolV2.handleMessage(context, message.getClosedGroupUpdateV2().get(), message.getTimestamp(), envelope.getSource(), content.getSender()); handleUnknownGroupMessage(content, message.getGroupInfo().get());
} }
if (message.isEndSession()) {
handleEndSessionMessage(content, smsMessageId);
} else if (message.isGroupUpdate()) {
handleGroupMessage(content, message, smsMessageId);
} else if (message.isExpirationUpdate()) {
handleExpirationUpdate(content, message, smsMessageId);
} else if (isMediaMessage) {
handleMediaMessage(content, message, smsMessageId, Optional.absent());
} else if (message.getBody().isPresent()) {
handleTextMessage(content, message, smsMessageId, Optional.absent());
}
if (message.getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getGroupInfo().get()))) { if (message.getProfileKey().isPresent() && message.getProfileKey().get().length == 32) {
handleUnknownGroupMessage(content, message.getGroupInfo().get()); SessionMetaProtocol.handleProfileKeyUpdate(context, content);
} }
if (message.getProfileKey().isPresent() && message.getProfileKey().get().length == 32) { if (SessionMetaProtocol.shouldSendDeliveryReceipt(message, Address.Companion.fromSerialized(content.getSender()))) {
SessionMetaProtocol.handleProfileKeyUpdate(context, content); handleNeedsDeliveryReceipt(content, message);
}
if (SessionMetaProtocol.shouldSendDeliveryReceipt(message, Address.Companion.fromSerialized(content.getSender()))) {
handleNeedsDeliveryReceipt(content, message);
}
} }
} else if (content.getSyncMessage().isPresent()) { } else if (content.getSyncMessage().isPresent()) {
throw new UnsupportedOperationException("Device link operations are not supported!"); throw new UnsupportedOperationException("Device link operations are not supported!");
// TextSecurePreferences.setMultiDevice(context, true);
//
// SignalServiceSyncMessage syncMessage = content.getSyncMessage().get();
//
// if (syncMessage.getSent().isPresent()) handleSynchronizeSentMessage(content, syncMessage.getSent().get());
// else if (syncMessage.getRequest().isPresent()) handleSynchronizeRequestMessage(syncMessage.getRequest().get());
// else if (syncMessage.getRead().isPresent()) handleSynchronizeReadMessage(syncMessage.getRead().get(), content.getTimestamp());
// else if (syncMessage.getVerified().isPresent()) handleSynchronizeVerifiedMessage(syncMessage.getVerified().get());
// else if (syncMessage.getStickerPackOperations().isPresent()) handleSynchronizeStickerPackOperation(syncMessage.getStickerPackOperations().get());
// else if (syncMessage.getContacts().isPresent()) SyncMessagesProtocol.handleContactSyncMessage(context, content, syncMessage.getContacts().get());
// else if (syncMessage.getGroups().isPresent()) SyncMessagesProtocol.handleClosedGroupSyncMessage(context, content, syncMessage.getGroups().get());
// else if (syncMessage.getOpenGroups().isPresent()) SyncMessagesProtocol.handleOpenGroupSyncMessage(context, content, syncMessage.getOpenGroups().get());
// else if (syncMessage.getBlockedList().isPresent()) SyncMessagesProtocol.handleBlockedContactsSyncMessage(context, content, syncMessage.getBlockedList().get());
// else Log.w(TAG, "Contains no known sync types...");
} else if (content.getReceiptMessage().isPresent()) { } else if (content.getReceiptMessage().isPresent()) {
SignalServiceReceiptMessage message = content.getReceiptMessage().get(); SignalServiceReceiptMessage message = content.getReceiptMessage().get();
@ -1250,21 +1230,10 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
} else { } else {
String publicKey = message.getDestination().get(); String publicKey = message.getDestination().get();
String userPublicKey = TextSecurePreferences.getLocalNumber(context); String userPublicKey = TextSecurePreferences.getLocalNumber(context);
Set<String> allUserDevices = org.session.libsignal.service.loki.protocol.shelved.multidevice.MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey); if (publicKey.equals(userPublicKey)) {
if (allUserDevices.contains(publicKey)) {
return Recipient.from(context, Address.Companion.fromSerialized(userPublicKey), false); return Recipient.from(context, Address.Companion.fromSerialized(userPublicKey), false);
} else { } else {
try { return Recipient.from(context, Address.Companion.fromSerialized(publicKey), false);
// TODO: Burn this with fire when we can
PromiseUtilities.timeout(FileServerAPI.shared.getDeviceLinks(publicKey, false), 6000).get();
String masterPublicKey = org.session.libsignal.service.loki.protocol.shelved.multidevice.MultiDeviceProtocol.shared.getMasterDevice(publicKey);
if (masterPublicKey == null) {
masterPublicKey = publicKey;
}
return Recipient.from(context, Address.Companion.fromSerialized(masterPublicKey), false);
} catch (Exception e) {
return Recipient.from(context, Address.Companion.fromSerialized(publicKey), false);
}
} }
} }
} }
@ -1282,21 +1251,10 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
return Recipient.from(context, Address.Companion.fromSerialized(publicKey), false); return Recipient.from(context, Address.Companion.fromSerialized(publicKey), false);
} else { } else {
String userPublicKey = TextSecurePreferences.getLocalNumber(context); String userPublicKey = TextSecurePreferences.getLocalNumber(context);
Set<String> allUserDevices = org.session.libsignal.service.loki.protocol.shelved.multidevice.MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey); if (publicKey.equals(userPublicKey)) {
if (allUserDevices.contains(publicKey)) {
return Recipient.from(context, Address.Companion.fromSerialized(userPublicKey), false); return Recipient.from(context, Address.Companion.fromSerialized(userPublicKey), false);
} else { } else {
try { return Recipient.from(context, Address.Companion.fromSerialized(publicKey), false);
// TODO: Burn this with fire when we can
PromiseUtilities.timeout(FileServerAPI.shared.getDeviceLinks(publicKey, false), 6000).get();
String masterPublicKey = org.session.libsignal.service.loki.protocol.shelved.multidevice.MultiDeviceProtocol.shared.getMasterDevice(publicKey);
if (masterPublicKey == null) {
masterPublicKey = publicKey;
}
return Recipient.from(context, Address.Companion.fromSerialized(masterPublicKey), false);
} catch (Exception e) {
return Recipient.from(context, Address.Companion.fromSerialized(publicKey), false);
}
} }
} }
} }
@ -1330,9 +1288,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
Recipient sender = Recipient.from(context, Address.Companion.fromSerialized(content.getSender()), false); Recipient sender = Recipient.from(context, Address.Companion.fromSerialized(content.getSender()), false);
if (content.getDeviceLink().isPresent()) { if (content.getDataMessage().isPresent()) {
return false;
} else if (content.getDataMessage().isPresent()) {
SignalServiceDataMessage message = content.getDataMessage().get(); SignalServiceDataMessage message = content.getDataMessage().get();
Recipient conversation = getMessageDestination(content, message); Recipient conversation = getMessageDestination(content, message);

View File

@ -9,9 +9,9 @@ class SelectContactsLoader(context: Context, val usersToExclude: Set<String>) :
override fun loadInBackground(): List<String> { override fun loadInBackground(): List<String> {
val contacts = ContactUtilities.getAllContacts(context) val contacts = ContactUtilities.getAllContacts(context)
return contacts.filter { contact -> return contacts.filter { contact ->
!contact.recipient.isGroupRecipient && !contact.isOurDevice && !contact.isSlave && !usersToExclude.contains(contact.recipient.address.toString()) !contact.isGroupRecipient && !usersToExclude.contains(contact.address.toString())
}.map { }.map {
it.recipient.address.toString() it.address.toString()
} }
} }
} }

View File

@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.loki.fragments
import android.content.Context import android.content.Context
import network.loki.messenger.R import network.loki.messenger.R
import org.thoughtcrime.securesms.loki.utilities.Contact
import org.thoughtcrime.securesms.loki.utilities.ContactUtilities import org.thoughtcrime.securesms.loki.utilities.ContactUtilities
import org.session.libsession.messaging.threads.recipients.Recipient import org.session.libsession.messaging.threads.recipients.Recipient
import org.thoughtcrime.securesms.util.AsyncLoader import org.thoughtcrime.securesms.util.AsyncLoader
@ -28,9 +27,9 @@ class ContactSelectionListLoader(context: Context, val mode: Int, val filter: St
override fun loadInBackground(): List<ContactSelectionListItem> { override fun loadInBackground(): List<ContactSelectionListItem> {
val contacts = ContactUtilities.getAllContacts(context).filter { val contacts = ContactUtilities.getAllContacts(context).filter {
if (filter.isNullOrEmpty()) return@filter true if (filter.isNullOrEmpty()) return@filter true
it.recipient.toShortString().contains(filter.trim(), true) || it.recipient.address.serialize().contains(filter.trim(), true) it.toShortString().contains(filter.trim(), true) || it.address.serialize().contains(filter.trim(), true)
}.sortedBy { }.sortedBy {
it.recipient.toShortString() it.toShortString()
} }
val list = mutableListOf<ContactSelectionListItem>() val list = mutableListOf<ContactSelectionListItem>()
if (isFlagSet(DisplayMode.FLAG_CLOSED_GROUPS)) { if (isFlagSet(DisplayMode.FLAG_CLOSED_GROUPS)) {
@ -45,27 +44,27 @@ class ContactSelectionListLoader(context: Context, val mode: Int, val filter: St
return list return list
} }
private fun getContacts(contacts: List<Contact>): List<ContactSelectionListItem> { private fun getContacts(contacts: List<Recipient>): List<ContactSelectionListItem> {
return getItems(contacts, context.getString(R.string.fragment_contact_selection_contacts_title)) { return getItems(contacts, context.getString(R.string.fragment_contact_selection_contacts_title)) {
!it.recipient.isGroupRecipient && !it.isOurDevice && !it.isSlave !it.isGroupRecipient
} }
} }
private fun getClosedGroups(contacts: List<Contact>): List<ContactSelectionListItem> { private fun getClosedGroups(contacts: List<Recipient>): List<ContactSelectionListItem> {
return getItems(contacts, context.getString(R.string.fragment_contact_selection_closed_groups_title)) { return getItems(contacts, context.getString(R.string.fragment_contact_selection_closed_groups_title)) {
it.recipient.address.isClosedGroup it.address.isClosedGroup
} }
} }
private fun getOpenGroups(contacts: List<Contact>): List<ContactSelectionListItem> { private fun getOpenGroups(contacts: List<Recipient>): List<ContactSelectionListItem> {
return getItems(contacts, context.getString(R.string.fragment_contact_selection_open_groups_title)) { return getItems(contacts, context.getString(R.string.fragment_contact_selection_open_groups_title)) {
it.recipient.address.isOpenGroup it.address.isOpenGroup
} }
} }
private fun getItems(contacts: List<Contact>, title: String, contactFilter: (Contact) -> Boolean): List<ContactSelectionListItem> { private fun getItems(contacts: List<Recipient>, title: String, contactFilter: (Recipient) -> Boolean): List<ContactSelectionListItem> {
val items = contacts.filter(contactFilter).map { val items = contacts.filter(contactFilter).map {
ContactSelectionListItem.Contact(it.recipient) ContactSelectionListItem.Contact(it)
} }
if (items.isEmpty()) return listOf() if (items.isEmpty()) return listOf()
val header = ContactSelectionListItem.Header(title) val header = ContactSelectionListItem.Header(title)

View File

@ -3,49 +3,19 @@ package org.thoughtcrime.securesms.loki.utilities
import android.content.Context import android.content.Context
import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.database.DatabaseFactory
import org.session.libsession.messaging.threads.recipients.Recipient import org.session.libsession.messaging.threads.recipients.Recipient
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsignal.service.loki.protocol.shelved.multidevice.MultiDeviceProtocol
data class Contact(
val recipient: Recipient,
val isSlave: Boolean,
val isOurDevice: Boolean
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
other as Contact
return recipient == other.recipient
}
override fun hashCode(): Int {
return recipient.hashCode()
}
}
object ContactUtilities { object ContactUtilities {
@JvmStatic @JvmStatic
fun getAllContacts(context: Context): Set<Contact> { fun getAllContacts(context: Context): Set<Recipient> {
val threadDatabase = DatabaseFactory.getThreadDatabase(context) val threadDatabase = DatabaseFactory.getThreadDatabase(context)
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
val lokiAPIDatabase = DatabaseFactory.getLokiAPIDatabase(context)
val userDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey)
val cursor = threadDatabase.conversationList val cursor = threadDatabase.conversationList
val result = mutableSetOf<Contact>() val result = mutableSetOf<Recipient>()
threadDatabase.readerFor(cursor).use { reader -> threadDatabase.readerFor(cursor).use { reader ->
while (reader.next != null) { while (reader.next != null) {
val thread = reader.current val thread = reader.current
val recipient = thread.recipient val recipient = thread.recipient
val publicKey = recipient.address.serialize() result.add(recipient)
val isUserDevice = userDevices.contains(publicKey)
var isSlave = false
if (!recipient.isGroupRecipient) {
val deviceLinks = lokiAPIDatabase.getDeviceLinks(publicKey)
isSlave = deviceLinks.find { it.slavePublicKey == publicKey } != null
}
result.add(Contact(recipient, isSlave, isUserDevice))
} }
} }
return result return result

View File

@ -21,7 +21,6 @@ import org.thoughtcrime.securesms.jobs.SendReadReceiptJob;
import org.session.libsignal.utilities.logging.Log; import org.session.libsignal.utilities.logging.Log;
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol; import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol;
import org.thoughtcrime.securesms.service.ExpiringMessageManager; import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.session.libsignal.service.loki.protocol.shelved.multidevice.MultiDeviceProtocol;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -85,13 +84,9 @@ public class MarkReadReceiver extends BroadcastReceiver {
// Loki - Check whether we want to send a read receipt to this user // Loki - Check whether we want to send a read receipt to this user
if (!SessionMetaProtocol.shouldSendReadReceipt(address)) { continue; } if (!SessionMetaProtocol.shouldSendReadReceipt(address)) { continue; }
// Loki - Take into account multi device // Loki - Take into account multi device
Set<String> linkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(address.serialize()); ApplicationContext.getInstance(context)
for (String device : linkedDevices) { .getJobManager()
Address deviceAsAddress = Address.Companion.fromExternal(context, device); .add(new SendReadReceiptJob(address, timestamps));
ApplicationContext.getInstance(context)
.getJobManager()
.add(new SendReadReceiptJob(deviceAsAddress, timestamps));
}
} }
} }