mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 20:15:21 +00:00
Forward messages from secondary devices to primary device.
This commit is contained in:
parent
3c5ef19ca7
commit
21e529c6c9
@ -128,6 +128,7 @@ import org.thoughtcrime.securesms.contactshare.SimpleTextWatcher;
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
|
||||
import org.thoughtcrime.securesms.crypto.SecurityEvent;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.Database;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.DraftDatabase;
|
||||
import org.thoughtcrime.securesms.database.DraftDatabase.Draft;
|
||||
@ -158,6 +159,7 @@ import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.FriendRequestViewDelegate;
|
||||
import org.thoughtcrime.securesms.loki.LokiAPIUtilities;
|
||||
import org.thoughtcrime.securesms.loki.LokiThreadDatabase;
|
||||
import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
|
||||
import org.thoughtcrime.securesms.loki.LokiThreadDatabaseDelegate;
|
||||
import org.thoughtcrime.securesms.loki.LokiUserDatabase;
|
||||
import org.thoughtcrime.securesms.loki.MentionCandidateSelectionView;
|
||||
@ -2988,7 +2990,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
// region Loki
|
||||
@Override
|
||||
public void acceptFriendRequest(@NotNull MessageRecord friendRequest) {
|
||||
String contactID = DatabaseFactory.getThreadDatabase(this).getRecipientForThreadId(this.threadId).getAddress().toString();
|
||||
// Send the accept to the original friend request thread id
|
||||
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(this);
|
||||
long originalThreadID = lokiMessageDatabase.getOriginalThreadID(friendRequest.id);
|
||||
long threadId = originalThreadID < 0 ? this.threadId : originalThreadID;
|
||||
|
||||
String contactID = DatabaseFactory.getThreadDatabase(this).getRecipientForThreadId(threadId).getAddress().toString();
|
||||
SignalServiceMessageSender messageSender = ApplicationContext.getInstance(this).communicationModule.provideSignalMessageSender();
|
||||
SignalServiceAddress address = new SignalServiceAddress(contactID);
|
||||
SignalServiceDataMessage message = new SignalServiceDataMessage(System.currentTimeMillis(), "");
|
||||
@ -2996,8 +3003,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
AsyncTask.execute(() -> {
|
||||
try {
|
||||
messageSender.sendMessage(0, address, Optional.absent(), message); // The message ID doesn't matter
|
||||
DatabaseFactory.getLokiThreadDatabase(context).setFriendRequestStatus(this.threadId, LokiThreadFriendRequestStatus.FRIENDS);
|
||||
DatabaseFactory.getLokiMessageDatabase(context).setFriendRequestStatus(friendRequest.id, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED);
|
||||
DatabaseFactory.getLokiThreadDatabase(context).setFriendRequestStatus(threadId, LokiThreadFriendRequestStatus.FRIENDS);
|
||||
lokiMessageDatabase.setFriendRequestStatus(friendRequest.id, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED);
|
||||
} catch (Exception e) {
|
||||
Log.d("Loki", "Failed to send background message to: " + contactID + ".");
|
||||
}
|
||||
@ -3006,8 +3013,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
@Override
|
||||
public void rejectFriendRequest(@NotNull MessageRecord friendRequest) {
|
||||
DatabaseFactory.getLokiThreadDatabase(this).setFriendRequestStatus(this.threadId, LokiThreadFriendRequestStatus.NONE);
|
||||
String contactID = DatabaseFactory.getThreadDatabase(this).getRecipientForThreadId(this.threadId).getAddress().toString();
|
||||
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(this);
|
||||
long originalThreadID = lokiMessageDatabase.getOriginalThreadID(friendRequest.id);
|
||||
long threadId = originalThreadID < 0 ? this.threadId : originalThreadID;
|
||||
|
||||
DatabaseFactory.getLokiThreadDatabase(this).setFriendRequestStatus(threadId, LokiThreadFriendRequestStatus.NONE);
|
||||
String contactID = DatabaseFactory.getThreadDatabase(this).getRecipientForThreadId(threadId).getAddress().toString();
|
||||
DatabaseFactory.getLokiPreKeyBundleDatabase(this).removePreKeyBundle(contactID);
|
||||
}
|
||||
// endregion
|
||||
|
@ -70,6 +70,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
private static final int lokiV1 = 22;
|
||||
private static final int lokiV2 = 23;
|
||||
private static final int lokiV3 = 24;
|
||||
private static final int lokiV4 = 25;
|
||||
|
||||
private static final int DATABASE_VERSION = lokiV3; // Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes
|
||||
private static final String DATABASE_NAME = "signal.db";
|
||||
@ -128,7 +129,8 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
db.execSQL(LokiAPIDatabase.getCreatePairingAuthorisationTableCommand());
|
||||
db.execSQL(LokiPreKeyBundleDatabase.getCreateTableCommand());
|
||||
db.execSQL(LokiPreKeyRecordDatabase.getCreateTableCommand());
|
||||
db.execSQL(LokiMessageDatabase.getCreateTableCommand());
|
||||
db.execSQL(LokiMessageDatabase.getCreateMessageFriendRequestTableCommand());
|
||||
db.execSQL(LokiMessageDatabase.getCreateMessageToThreadMappingTableCommand());
|
||||
db.execSQL(LokiThreadDatabase.getCreateFriendRequestTableCommand());
|
||||
db.execSQL(LokiThreadDatabase.getCreateSessionResetTableCommand());
|
||||
db.execSQL(LokiThreadDatabase.getCreatePublicChatTableCommand());
|
||||
@ -504,6 +506,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
db.execSQL("ALTER TABLE part ADD COLUMN url TEXT");
|
||||
}
|
||||
|
||||
if (oldVersion < lokiV4) {
|
||||
db.execSQL(LokiMessageDatabase.getCreateMessageToThreadMappingTableCommand());
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
|
@ -97,6 +97,7 @@ import org.thoughtcrime.securesms.util.IdentityUtil;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.concurrent.SettableFuture;
|
||||
import org.whispersystems.libsignal.state.PreKeyBundle;
|
||||
import org.whispersystems.libsignal.state.SignalProtocolStore;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
@ -749,13 +750,16 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
@NonNull Optional<Long> messageServerIDOrNull)
|
||||
throws StorageFailedException
|
||||
{
|
||||
notifyTypingStoppedFromIncomingMessage(getMessageDestination(content, message), content.getSender(), content.getSenderDevice());
|
||||
Recipient originalRecipient = getMessageDestination(content, message);
|
||||
Recipient primaryDeviceRecipient = getMessagePrimaryDestination(content, message);
|
||||
|
||||
notifyTypingStoppedFromIncomingMessage(primaryDeviceRecipient, content.getSender(), content.getSenderDevice());
|
||||
|
||||
Optional<QuoteModel> quote = getValidatedQuote(message.getQuote());
|
||||
Optional<List<Contact>> sharedContacts = getContacts(message.getSharedContacts());
|
||||
Optional<List<LinkPreview>> linkPreviews = getLinkPreviews(message.getPreviews(), message.getBody().or(""));
|
||||
Optional<Attachment> sticker = getStickerAttachment(message.getSticker());
|
||||
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(Address.fromExternal(context, content.getSender()), message.getTimestamp(), -1,
|
||||
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(primaryDeviceRecipient.getAddress(), message.getTimestamp(), -1,
|
||||
message.getExpiresInSeconds() * 1000L, false, content.isNeedsReceipt(), message.getBody(), message.getGroupInfo(), message.getAttachments(),
|
||||
quote, sharedContacts, linkPreviews, sticker);
|
||||
|
||||
@ -798,8 +802,14 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
// Loki - Store message server ID
|
||||
updateGroupChatMessageServerID(messageServerIDOrNull, insertResult);
|
||||
|
||||
// Loki - Update mapping of message to original thread id
|
||||
if (insertResult.isPresent()) {
|
||||
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
|
||||
|
||||
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
|
||||
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context);
|
||||
long originalThreadId = threadDatabase.getThreadIdFor(originalRecipient);
|
||||
lokiMessageDatabase.setOriginalThreadID(insertResult.get().getMessageId(), originalThreadId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -912,20 +922,21 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
{
|
||||
SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
|
||||
String body = message.getBody().isPresent() ? message.getBody().get() : "";
|
||||
Recipient recipient = getMessageDestination(content, message);
|
||||
Recipient originalRecipient = getMessageDestination(content, message);
|
||||
Recipient primaryDeviceRecipient = message.isGroupUpdate() ? originalRecipient : getMessagePrimaryDestination(content, message);
|
||||
|
||||
if (message.getExpiresInSeconds() != recipient.getExpireMessages()) {
|
||||
if (message.getExpiresInSeconds() != originalRecipient.getExpireMessages()) {
|
||||
handleExpirationUpdate(content, message, Optional.absent());
|
||||
}
|
||||
|
||||
Long threadId;
|
||||
Long threadId = null;
|
||||
|
||||
if (smsMessageId.isPresent() && !message.getGroupInfo().isPresent()) {
|
||||
threadId = database.updateBundleMessageBody(smsMessageId.get(), body).second;
|
||||
} else {
|
||||
notifyTypingStoppedFromIncomingMessage(recipient, content.getSender(), content.getSenderDevice());
|
||||
notifyTypingStoppedFromIncomingMessage(primaryDeviceRecipient, content.getSender(), content.getSenderDevice());
|
||||
|
||||
IncomingTextMessage _textMessage = new IncomingTextMessage(Address.fromSerialized(content.getSender()),
|
||||
IncomingTextMessage _textMessage = new IncomingTextMessage(primaryDeviceRecipient.getAddress(),
|
||||
content.getSenderDevice(),
|
||||
message.getTimestamp(), body,
|
||||
message.getGroupInfo(),
|
||||
@ -940,8 +951,11 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
// Insert the message into the database
|
||||
Optional<InsertResult> insertResult = database.insertMessageInbox(textMessage);
|
||||
|
||||
if (insertResult.isPresent()) threadId = insertResult.get().getThreadId();
|
||||
else threadId = null;
|
||||
Long messageId = null;
|
||||
if (insertResult.isPresent()) {
|
||||
threadId = insertResult.get().getThreadId();
|
||||
messageId = insertResult.get().getMessageId();
|
||||
}
|
||||
|
||||
if (smsMessageId.isPresent()) database.deleteMessage(smsMessageId.get());
|
||||
|
||||
@ -954,6 +968,14 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
// Loki - Store message server ID
|
||||
updateGroupChatMessageServerID(messageServerIDOrNull, insertResult);
|
||||
|
||||
// Loki - Update mapping of message to original thread id
|
||||
if (messageId != null) {
|
||||
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
|
||||
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context);
|
||||
long originalThreadId = threadDatabase.getThreadIdFor(originalRecipient);
|
||||
lokiMessageDatabase.setOriginalThreadID(messageId, originalThreadId);
|
||||
}
|
||||
|
||||
boolean isGroupMessage = message.getGroupInfo().isPresent();
|
||||
if (threadId != null && !isGroupMessage) {
|
||||
MessageNotifier.updateNotification(context, threadId);
|
||||
@ -1496,6 +1518,33 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
}
|
||||
}
|
||||
|
||||
private Recipient getMessagePrimaryDestination(SignalServiceContent content, SignalServiceDataMessage message) {
|
||||
if (message.getGroupInfo().isPresent()) {
|
||||
return Recipient.from(context, Address.fromSerialized(GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId(), false)), false);
|
||||
} else {
|
||||
SettableFuture<String> device = new SettableFuture<>();
|
||||
String contentSender = content.getSender();
|
||||
|
||||
// Get the primary device
|
||||
LokiStorageAPI.shared.getPrimaryDevicePublicKey(contentSender).success(primaryDevice -> {
|
||||
String publicKey = primaryDevice == null ? contentSender : primaryDevice;
|
||||
device.set(publicKey);
|
||||
return Unit.INSTANCE;
|
||||
}).fail(exception -> {
|
||||
device.set(contentSender);
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
|
||||
try {
|
||||
String primarySender = device.get();
|
||||
return Recipient.from(context, Address.fromSerialized(primarySender), false);
|
||||
} catch (Exception e) {
|
||||
Log.d("Loki", "Failed to get primary device public key for message. " + e.getMessage());
|
||||
return Recipient.from(context, Address.fromSerialized(content.getSender()), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Recipient getMessageDestination(SignalServiceContent content, SignalServiceDataMessage message) {
|
||||
if (message.getGroupInfo().isPresent()) {
|
||||
return Recipient.from(context, Address.fromSerialized(GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId(), false)), false);
|
||||
|
@ -12,11 +12,14 @@ import org.whispersystems.signalservice.loki.messaging.LokiMessageFriendRequestS
|
||||
class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiMessageDatabaseProtocol {
|
||||
|
||||
companion object {
|
||||
private val tableName = "loki_message_friend_request_database"
|
||||
private val messageFriendRequestTableName = "loki_message_friend_request_database"
|
||||
private val messageThreadMappingTableName = "loki_message_thread_mapping_database"
|
||||
private val messageID = "message_id"
|
||||
private val serverID = "server_id"
|
||||
private val friendRequestStatus = "friend_request_status"
|
||||
@JvmStatic val createTableCommand = "CREATE TABLE $tableName ($messageID INTEGER PRIMARY KEY, $serverID INTEGER DEFAULT 0, $friendRequestStatus INTEGER DEFAULT 0);"
|
||||
private val threadID = "thread_id"
|
||||
@JvmStatic val createMessageFriendRequestTableCommand = "CREATE TABLE $messageFriendRequestTableName ($messageID INTEGER PRIMARY KEY, $serverID INTEGER DEFAULT 0, $friendRequestStatus INTEGER DEFAULT 0);"
|
||||
@JvmStatic val createMessageToThreadMappingTableCommand = "CREATE TABLE $messageThreadMappingTableName ($messageID INTEGER PRIMARY KEY, $threadID INTEGER);"
|
||||
}
|
||||
|
||||
override fun getQuoteServerID(quoteID: Long, quoteeHexEncodedPublicKey: String): Long? {
|
||||
@ -26,14 +29,14 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
||||
|
||||
fun getServerID(messageID: Long): Long? {
|
||||
val database = databaseHelper.readableDatabase
|
||||
return database.get(tableName, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
|
||||
return database.get(messageFriendRequestTableName, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
|
||||
cursor.getInt(Companion.serverID)
|
||||
}?.toLong()
|
||||
}
|
||||
|
||||
fun getMessageID(serverID: Long): Long? {
|
||||
val database = databaseHelper.readableDatabase
|
||||
return database.get(tableName, "${Companion.serverID} = ?", arrayOf( serverID.toString() )) { cursor ->
|
||||
return database.get(messageFriendRequestTableName, "${Companion.serverID} = ?", arrayOf( serverID.toString() )) { cursor ->
|
||||
cursor.getInt(messageID)
|
||||
}?.toLong()
|
||||
}
|
||||
@ -43,12 +46,27 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
||||
val contentValues = ContentValues(2)
|
||||
contentValues.put(Companion.messageID, messageID)
|
||||
contentValues.put(Companion.serverID, serverID)
|
||||
database.insertOrUpdate(tableName, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
||||
database.insertOrUpdate(messageFriendRequestTableName, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
||||
}
|
||||
|
||||
fun getOriginalThreadID(messageID: Long): Long {
|
||||
val database = databaseHelper.readableDatabase
|
||||
return database.get(messageThreadMappingTableName, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
|
||||
cursor.getInt(Companion.threadID)
|
||||
}?.toLong() ?: -1L
|
||||
}
|
||||
|
||||
fun setOriginalThreadID(messageID: Long, threadID: Long) {
|
||||
val database = databaseHelper.writableDatabase
|
||||
val contentValues = ContentValues(2)
|
||||
contentValues.put(Companion.messageID, messageID)
|
||||
contentValues.put(Companion.threadID, threadID)
|
||||
database.insertOrUpdate(messageThreadMappingTableName, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
||||
}
|
||||
|
||||
fun getFriendRequestStatus(messageID: Long): LokiMessageFriendRequestStatus {
|
||||
val database = databaseHelper.readableDatabase
|
||||
val result = database.get(tableName, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
|
||||
val result = database.get(messageFriendRequestTableName, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
|
||||
cursor.getInt(friendRequestStatus)
|
||||
}
|
||||
return if (result != null) {
|
||||
@ -63,7 +81,7 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
||||
val contentValues = ContentValues(2)
|
||||
contentValues.put(Companion.messageID, messageID)
|
||||
contentValues.put(Companion.friendRequestStatus, friendRequestStatus.rawValue)
|
||||
database.insertOrUpdate(tableName, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
||||
database.insertOrUpdate(messageFriendRequestTableName, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
||||
val threadID = DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageID)
|
||||
notifyConversationListeners(threadID)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user