mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-23 18:15:22 +00:00
Add contacts migration
This commit is contained in:
parent
04b62df83c
commit
d7afcd07f8
@ -30,26 +30,25 @@ import androidx.multidex.MultiDexApplication;
|
|||||||
import org.conscrypt.Conscrypt;
|
import org.conscrypt.Conscrypt;
|
||||||
import org.session.libsession.avatars.AvatarHelper;
|
import org.session.libsession.avatars.AvatarHelper;
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration;
|
import org.session.libsession.messaging.MessagingModuleConfiguration;
|
||||||
import org.session.libsession.messaging.mentions.MentionsManager;
|
import org.session.libsession.messaging.contacts.Contact;
|
||||||
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier;
|
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier;
|
||||||
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPollerV2;
|
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPollerV2;
|
||||||
import org.session.libsession.messaging.sending_receiving.pollers.Poller;
|
import org.session.libsession.messaging.sending_receiving.pollers.Poller;
|
||||||
import org.session.libsession.snode.SnodeModule;
|
import org.session.libsession.snode.SnodeModule;
|
||||||
import org.session.libsession.utilities.Address;
|
import org.session.libsession.utilities.Address;
|
||||||
import org.session.libsession.utilities.IdentityKeyUtil;
|
|
||||||
import org.session.libsession.utilities.ProfileKeyUtil;
|
|
||||||
import org.session.libsession.utilities.ProfilePictureUtilities;
|
import org.session.libsession.utilities.ProfilePictureUtilities;
|
||||||
import org.session.libsession.utilities.SSKEnvironment;
|
import org.session.libsession.utilities.SSKEnvironment;
|
||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
import org.session.libsession.utilities.Util;
|
import org.session.libsession.utilities.Util;
|
||||||
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWrapper;
|
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWrapper;
|
||||||
import org.session.libsession.utilities.dynamiclanguage.LocaleParser;
|
import org.session.libsession.utilities.dynamiclanguage.LocaleParser;
|
||||||
import org.session.libsignal.database.LokiAPIDatabaseProtocol;
|
import org.session.libsession.utilities.recipients.Recipient;
|
||||||
import org.session.libsignal.utilities.Log;
|
import org.session.libsignal.utilities.Log;
|
||||||
import org.session.libsignal.utilities.ThreadUtils;
|
import org.session.libsignal.utilities.ThreadUtils;
|
||||||
import org.signal.aesgcmprovider.AesGcmProvider;
|
import org.signal.aesgcmprovider.AesGcmProvider;
|
||||||
import org.thoughtcrime.securesms.components.TypingStatusSender;
|
import org.thoughtcrime.securesms.components.TypingStatusSender;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
|
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||||
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule;
|
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule;
|
||||||
import org.thoughtcrime.securesms.jobmanager.DependencyInjector;
|
import org.thoughtcrime.securesms.jobmanager.DependencyInjector;
|
||||||
@ -65,8 +64,10 @@ import org.thoughtcrime.securesms.loki.api.BackgroundPollWorker;
|
|||||||
import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager;
|
import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager;
|
||||||
import org.thoughtcrime.securesms.loki.api.OpenGroupManager;
|
import org.thoughtcrime.securesms.loki.api.OpenGroupManager;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
||||||
|
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.Broadcaster;
|
import org.thoughtcrime.securesms.loki.utilities.Broadcaster;
|
||||||
|
import org.thoughtcrime.securesms.loki.utilities.ContactUtilities;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.FcmUtils;
|
import org.thoughtcrime.securesms.loki.utilities.FcmUtils;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities;
|
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities;
|
||||||
import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
|
import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
|
||||||
@ -84,14 +85,12 @@ import org.webrtc.PeerConnectionFactory;
|
|||||||
import org.webrtc.PeerConnectionFactory.InitializationOptions;
|
import org.webrtc.PeerConnectionFactory.InitializationOptions;
|
||||||
import org.webrtc.voiceengine.WebRtcAudioManager;
|
import org.webrtc.voiceengine.WebRtcAudioManager;
|
||||||
import org.webrtc.voiceengine.WebRtcAudioUtils;
|
import org.webrtc.voiceengine.WebRtcAudioUtils;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import dagger.ObjectGraph;
|
import dagger.ObjectGraph;
|
||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
import kotlinx.coroutines.Job;
|
import kotlinx.coroutines.Job;
|
||||||
@ -152,8 +151,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
initializeDependencyInjection();
|
initializeDependencyInjection();
|
||||||
NotificationChannels.create(this);
|
NotificationChannels.create(this);
|
||||||
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
|
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
|
||||||
// Loki
|
|
||||||
// ========
|
|
||||||
AppContext.INSTANCE.configureKovenant();
|
AppContext.INSTANCE.configureKovenant();
|
||||||
messageNotifier = new OptimizedMessageNotifier(new DefaultMessageNotifier());
|
messageNotifier = new OptimizedMessageNotifier(new DefaultMessageNotifier());
|
||||||
broadcaster = new Broadcaster(this);
|
broadcaster = new Broadcaster(this);
|
||||||
@ -161,16 +158,14 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
||||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||||
MessagingModuleConfiguration.Companion.configure(this,
|
MessagingModuleConfiguration.Companion.configure(this,
|
||||||
DatabaseFactory.getStorage(this),
|
DatabaseFactory.getStorage(this),
|
||||||
DatabaseFactory.getAttachmentProvider(this));
|
DatabaseFactory.getAttachmentProvider(this));
|
||||||
SnodeModule.Companion.configure(apiDB, broadcaster);
|
SnodeModule.Companion.configure(apiDB, broadcaster);
|
||||||
resubmitProfilePictureIfNeeded();
|
resubmitProfilePictureIfNeeded();
|
||||||
if (userPublicKey != null) {
|
if (userPublicKey != null) {
|
||||||
registerForFCMIfNeeded(false);
|
registerForFCMIfNeeded(false);
|
||||||
}
|
}
|
||||||
// Set application UI mode (day/night theme) to the user selected one.
|
|
||||||
UiModeUtilities.setupUiModeToUserSelected(this);
|
UiModeUtilities.setupUiModeToUserSelected(this);
|
||||||
// ========
|
|
||||||
initializeExpiringMessageManager();
|
initializeExpiringMessageManager();
|
||||||
initializeTypingStatusRepository();
|
initializeTypingStatusRepository();
|
||||||
initializeTypingStatusSender();
|
initializeTypingStatusSender();
|
||||||
@ -188,12 +183,33 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
isAppVisible = true;
|
isAppVisible = true;
|
||||||
Log.i(TAG, "App is now visible.");
|
Log.i(TAG, "App is now visible.");
|
||||||
KeyCachingService.onAppForegrounded(this);
|
KeyCachingService.onAppForegrounded(this);
|
||||||
// Loki
|
|
||||||
|
boolean hasPerformedContactMigration = TextSecurePreferences.INSTANCE.hasPerformedContactMigration(this);
|
||||||
|
if (!hasPerformedContactMigration) {
|
||||||
|
TextSecurePreferences.INSTANCE.setPerformedContactMigration(this);
|
||||||
|
Set<Recipient> allContacts = ContactUtilities.getAllContacts(this);
|
||||||
|
SessionContactDatabase contactDB = DatabaseFactory.getSessionContactDatabase(this);
|
||||||
|
LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
|
||||||
|
for (Recipient recipient : allContacts) {
|
||||||
|
if (recipient.isGroupRecipient()) { continue; }
|
||||||
|
String sessionID = recipient.getAddress().serialize();
|
||||||
|
Contact contact = contactDB.getContactWithSessionID(sessionID);
|
||||||
|
if (contact == null) {
|
||||||
|
contact = new Contact(sessionID);
|
||||||
|
String name = userDB.getDisplayName(sessionID);
|
||||||
|
contact.setName(name);
|
||||||
|
contact.setProfilePictureURL(recipient.getProfileAvatar());
|
||||||
|
contact.setProfilePictureEncryptionKey(recipient.getProfileKey());
|
||||||
|
contact.setTrusted(true);
|
||||||
|
}
|
||||||
|
contactDB.setContact(contact);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (poller != null) {
|
if (poller != null) {
|
||||||
poller.setCaughtUp(false);
|
poller.setCaughtUp(false);
|
||||||
}
|
}
|
||||||
startPollingIfNeeded();
|
startPollingIfNeeded();
|
||||||
|
|
||||||
OpenGroupManager.INSTANCE.setAllCaughtUp(false);
|
OpenGroupManager.INSTANCE.setAllCaughtUp(false);
|
||||||
OpenGroupManager.INSTANCE.startPolling();
|
OpenGroupManager.INSTANCE.startPolling();
|
||||||
}
|
}
|
||||||
@ -204,7 +220,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
Log.i(TAG, "App is no longer visible.");
|
Log.i(TAG, "App is no longer visible.");
|
||||||
KeyCachingService.onAppBackgrounded(this);
|
KeyCachingService.onAppBackgrounded(this);
|
||||||
messageNotifier.setVisibleThread(-1);
|
messageNotifier.setVisibleThread(-1);
|
||||||
// Loki
|
|
||||||
if (poller != null) {
|
if (poller != null) {
|
||||||
poller.stopIfNeeded();
|
poller.stopIfNeeded();
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
|
|||||||
import org.thoughtcrime.securesms.loki.database.LokiBackupFilesDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiBackupFilesDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||||
|
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.SessionJobDatabase;
|
import org.thoughtcrime.securesms.loki.database.SessionJobDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
|
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
|
||||||
|
|
||||||
@ -52,16 +53,13 @@ public class DatabaseFactory {
|
|||||||
private final GroupReceiptDatabase groupReceiptDatabase;
|
private final GroupReceiptDatabase groupReceiptDatabase;
|
||||||
private final SearchDatabase searchDatabase;
|
private final SearchDatabase searchDatabase;
|
||||||
private final JobDatabase jobDatabase;
|
private final JobDatabase jobDatabase;
|
||||||
|
|
||||||
// Loki
|
|
||||||
private final LokiAPIDatabase lokiAPIDatabase;
|
private final LokiAPIDatabase lokiAPIDatabase;
|
||||||
private final LokiMessageDatabase lokiMessageDatabase;
|
private final LokiMessageDatabase lokiMessageDatabase;
|
||||||
private final LokiThreadDatabase lokiThreadDatabase;
|
private final LokiThreadDatabase lokiThreadDatabase;
|
||||||
|
private final LokiUserDatabase lokiUserDatabase;
|
||||||
private final LokiBackupFilesDatabase lokiBackupFilesDatabase;
|
private final LokiBackupFilesDatabase lokiBackupFilesDatabase;
|
||||||
private final SessionJobDatabase sessionJobDatabase;
|
private final SessionJobDatabase sessionJobDatabase;
|
||||||
private final SessionContactDatabase sessionContactDatabase;
|
private final SessionContactDatabase sessionContactDatabase;
|
||||||
|
|
||||||
// Refactor
|
|
||||||
private final Storage storage;
|
private final Storage storage;
|
||||||
private final DatabaseAttachmentProvider attachmentProvider;
|
private final DatabaseAttachmentProvider attachmentProvider;
|
||||||
|
|
||||||
@ -143,6 +141,10 @@ public class DatabaseFactory {
|
|||||||
return getInstance(context).lokiThreadDatabase;
|
return getInstance(context).lokiThreadDatabase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static LokiUserDatabase getLokiUserDatabase(Context context) {
|
||||||
|
return getInstance(context).lokiUserDatabase;
|
||||||
|
}
|
||||||
|
|
||||||
public static LokiBackupFilesDatabase getLokiBackupFilesDatabase(Context context) {
|
public static LokiBackupFilesDatabase getLokiBackupFilesDatabase(Context context) {
|
||||||
return getInstance(context).lokiBackupFilesDatabase;
|
return getInstance(context).lokiBackupFilesDatabase;
|
||||||
}
|
}
|
||||||
@ -194,6 +196,7 @@ public class DatabaseFactory {
|
|||||||
this.lokiAPIDatabase = new LokiAPIDatabase(context, databaseHelper);
|
this.lokiAPIDatabase = new LokiAPIDatabase(context, databaseHelper);
|
||||||
this.lokiMessageDatabase = new LokiMessageDatabase(context, databaseHelper);
|
this.lokiMessageDatabase = new LokiMessageDatabase(context, databaseHelper);
|
||||||
this.lokiThreadDatabase = new LokiThreadDatabase(context, databaseHelper);
|
this.lokiThreadDatabase = new LokiThreadDatabase(context, databaseHelper);
|
||||||
|
this.lokiUserDatabase = new LokiUserDatabase(context, databaseHelper);
|
||||||
this.lokiBackupFilesDatabase = new LokiBackupFilesDatabase(context, databaseHelper);
|
this.lokiBackupFilesDatabase = new LokiBackupFilesDatabase(context, databaseHelper);
|
||||||
this.storage = new Storage(context, databaseHelper);
|
this.storage = new Storage(context, databaseHelper);
|
||||||
this.attachmentProvider = new DatabaseAttachmentProvider(context, databaseHelper);
|
this.attachmentProvider = new DatabaseAttachmentProvider(context, databaseHelper);
|
||||||
|
@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
|
|||||||
import org.thoughtcrime.securesms.loki.database.LokiBackupFilesDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiBackupFilesDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||||
|
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
|
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.SessionJobDatabase;
|
import org.thoughtcrime.securesms.loki.database.SessionJobDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsMigration;
|
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsMigration;
|
||||||
@ -124,6 +125,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
|||||||
db.execSQL(LokiMessageDatabase.getCreateErrorMessageTableCommand());
|
db.execSQL(LokiMessageDatabase.getCreateErrorMessageTableCommand());
|
||||||
db.execSQL(LokiThreadDatabase.getCreateSessionResetTableCommand());
|
db.execSQL(LokiThreadDatabase.getCreateSessionResetTableCommand());
|
||||||
db.execSQL(LokiThreadDatabase.getCreatePublicChatTableCommand());
|
db.execSQL(LokiThreadDatabase.getCreatePublicChatTableCommand());
|
||||||
|
db.execSQL(LokiUserDatabase.getCreateDisplayNameTableCommand());
|
||||||
db.execSQL(LokiBackupFilesDatabase.getCreateTableCommand());
|
db.execSQL(LokiBackupFilesDatabase.getCreateTableCommand());
|
||||||
db.execSQL(SessionJobDatabase.getCreateSessionJobTableCommand());
|
db.execSQL(SessionJobDatabase.getCreateSessionJobTableCommand());
|
||||||
db.execSQL(LokiMessageDatabase.getUpdateMessageIDTableForType());
|
db.execSQL(LokiMessageDatabase.getUpdateMessageIDTableForType());
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
package org.thoughtcrime.securesms.loki.database
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.thoughtcrime.securesms.database.Database
|
||||||
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||||
|
import org.thoughtcrime.securesms.loki.utilities.get
|
||||||
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
|
|
||||||
|
class LokiUserDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
// Shared
|
||||||
|
private val displayName = "display_name"
|
||||||
|
// Display name cache
|
||||||
|
private val displayNameTable = "loki_user_display_name_database"
|
||||||
|
private val publicKey = "hex_encoded_public_key"
|
||||||
|
@JvmStatic val createDisplayNameTableCommand = "CREATE TABLE $displayNameTable ($publicKey TEXT PRIMARY KEY, $displayName TEXT);"
|
||||||
|
// Server display name cache
|
||||||
|
private val serverDisplayNameTable = "loki_user_server_display_name_database"
|
||||||
|
private val serverID = "server_id"
|
||||||
|
@JvmStatic val createServerDisplayNameTableCommand = "CREATE TABLE $serverDisplayNameTable ($publicKey TEXT, $serverID TEXT, $displayName TEXT, PRIMARY KEY ($publicKey, $serverID));"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDisplayName(publicKey: String): String? {
|
||||||
|
if (publicKey == TextSecurePreferences.getLocalNumber(context)) {
|
||||||
|
return TextSecurePreferences.getProfileName(context)
|
||||||
|
} else {
|
||||||
|
val database = databaseHelper.readableDatabase
|
||||||
|
val result = database.get(displayNameTable, "${Companion.publicKey} = ?", arrayOf( publicKey )) { cursor ->
|
||||||
|
cursor.getString(cursor.getColumnIndexOrThrow(displayName))
|
||||||
|
} ?: return null
|
||||||
|
val suffix = " (...${publicKey.substring(publicKey.count() - 8)})"
|
||||||
|
if (result.endsWith(suffix)) {
|
||||||
|
return result.substring(0..(result.count() - suffix.count()))
|
||||||
|
} else {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -764,12 +764,12 @@ object TextSecurePreferences {
|
|||||||
fun shouldUpdateProfile(context: Context, profileUpdateTime: Long) =
|
fun shouldUpdateProfile(context: Context, profileUpdateTime: Long) =
|
||||||
profileUpdateTime > getLongPreference(context, LAST_PROFILE_UPDATE_TIME, 0)
|
profileUpdateTime > getLongPreference(context, LAST_PROFILE_UPDATE_TIME, 0)
|
||||||
|
|
||||||
fun hasSeenFileServerInstabilityNotification(context: Context): Boolean {
|
fun hasPerformedContactMigration(context: Context): Boolean {
|
||||||
return getBooleanPreference(context, "has_seen_file_server_instability_notification", false)
|
return getBooleanPreference(context, "has_performed_contact_migration", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setHasSeenFileServerInstabilityNotification(context: Context) {
|
fun setPerformedContactMigration(context: Context) {
|
||||||
setBooleanPreference(context, "has_seen_file_server_instability_notification", true)
|
setBooleanPreference(context, "has_performed_contact_migration", true)
|
||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
@ -26,6 +26,7 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.annimon.stream.function.Consumer;
|
import com.annimon.stream.function.Consumer;
|
||||||
|
import com.esotericsoftware.kryo.util.Null;
|
||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
import org.session.libsession.database.StorageProtocol;
|
import org.session.libsession.database.StorageProtocol;
|
||||||
|
Loading…
Reference in New Issue
Block a user