Merge remote-tracking branch 'upstream/dev'

This commit is contained in:
Harris 2021-10-08 10:57:34 +11:00
commit 8f4a5c7469
111 changed files with 2050 additions and 1206 deletions

View File

@ -9,6 +9,7 @@ buildscript {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlinVersion"
classpath "com.google.gms:google-services:4.3.3"
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.38.1'
}
}
@ -19,6 +20,7 @@ apply plugin: 'witness'
apply plugin: 'kotlin-kapt'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'kotlinx-serialization'
apply plugin: 'dagger.hilt.android.plugin'
configurations.all {
exclude module: "commons-logging"
@ -70,9 +72,8 @@ dependencies {
implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0'
implementation 'com.melnykov:floatingactionbutton:1.3.0'
implementation 'com.google.zxing:android-integration:3.1.0'
implementation 'com.squareup.dagger:dagger:1.2.2'
annotationProcessor 'com.squareup.dagger:dagger-compiler:1.2.2'
kapt 'com.squareup.dagger:dagger-compiler:1.2.2'
implementation "com.google.dagger:hilt-android:2.38.1"
kapt "com.google.dagger:hilt-compiler:2.38.1"
implementation 'mobi.upod:time-duration-picker:1.1.3'
implementation 'com.google.zxing:core:3.2.1'
implementation ('com.davemorrissey.labs:subsampling-scale-image-view:3.6.0') {
@ -153,8 +154,8 @@ dependencies {
testImplementation 'org.robolectric:shadows-multidex:4.4'
}
def canonicalVersionCode = 222
def canonicalVersionName = "1.11.10"
def canonicalVersionCode = 227
def canonicalVersionName = "1.11.11"
def postFixSize = 10
def abiPostFix = ['armeabi-v7a' : 1,

View File

@ -15,6 +15,9 @@
*/
package org.thoughtcrime.securesms;
import static nl.komponents.kovenant.android.KovenantAndroid.startKovenant;
import static nl.komponents.kovenant.android.KovenantAndroid.stopKovenant;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
@ -30,6 +33,7 @@ import androidx.lifecycle.ProcessLifecycleOwner;
import org.conscrypt.Conscrypt;
import org.session.libsession.avatars.AvatarHelper;
import org.session.libsession.database.MessageDataProvider;
import org.session.libsession.messaging.MessagingModuleConfiguration;
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier;
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPollerV2;
@ -47,25 +51,27 @@ import org.session.libsignal.utilities.ThreadUtils;
import org.signal.aesgcmprovider.AesGcmProvider;
import org.thoughtcrime.securesms.components.TypingStatusSender;
import org.thoughtcrime.securesms.crypto.KeyPairUtilities;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule;
import org.thoughtcrime.securesms.jobmanager.DependencyInjector;
import org.thoughtcrime.securesms.database.JobDatabase;
import org.thoughtcrime.securesms.database.LokiAPIDatabase;
import org.thoughtcrime.securesms.database.Storage;
import org.thoughtcrime.securesms.database.LokiAPIDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.dependencies.DatabaseModule;
import org.thoughtcrime.securesms.groups.OpenGroupManager;
import org.thoughtcrime.securesms.home.HomeActivity;
import org.thoughtcrime.securesms.groups.OpenGroupManager;
import org.thoughtcrime.securesms.home.HomeActivity;
import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer;
import org.thoughtcrime.securesms.jobs.FastJobStorage;
import org.thoughtcrime.securesms.jobs.JobManagerFactories;
import org.thoughtcrime.securesms.logging.AndroidLogger;
import org.thoughtcrime.securesms.logging.PersistentLogger;
import org.thoughtcrime.securesms.logging.UncaughtExceptionLogger;
import org.thoughtcrime.securesms.home.HomeActivity;
import org.thoughtcrime.securesms.notifications.BackgroundPollWorker;
import org.thoughtcrime.securesms.notifications.LokiPushNotificationManager;
import org.thoughtcrime.securesms.groups.OpenGroupManager;
import org.thoughtcrime.securesms.database.LokiAPIDatabase;
import org.thoughtcrime.securesms.util.Broadcaster;
import org.thoughtcrime.securesms.notifications.FcmUtils;
import org.thoughtcrime.securesms.util.UiModeUtilities;
import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
import org.thoughtcrime.securesms.notifications.FcmUtils;
import org.thoughtcrime.securesms.notifications.LokiPushNotificationManager;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.notifications.OptimizedMessageNotifier;
import org.thoughtcrime.securesms.providers.BlobProvider;
@ -75,6 +81,8 @@ import org.thoughtcrime.securesms.service.UpdateApkRefreshListener;
import org.thoughtcrime.securesms.sskenvironment.ProfileManager;
import org.thoughtcrime.securesms.sskenvironment.ReadReceiptManager;
import org.thoughtcrime.securesms.sskenvironment.TypingStatusRepository;
import org.thoughtcrime.securesms.util.Broadcaster;
import org.thoughtcrime.securesms.util.UiModeUtilities;
import org.thoughtcrime.securesms.util.dynamiclanguage.LocaleParseHelper;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.PeerConnectionFactory.InitializationOptions;
@ -88,14 +96,14 @@ import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import dagger.ObjectGraph;
import javax.inject.Inject;
import dagger.hilt.EntryPoints;
import dagger.hilt.android.HiltAndroidApp;
import kotlin.Unit;
import kotlinx.coroutines.Job;
import network.loki.messenger.BuildConfig;
import static nl.komponents.kovenant.android.KovenantAndroid.startKovenant;
import static nl.komponents.kovenant.android.KovenantAndroid.stopKovenant;
/**
* Will be called once when the TextSecure process is created.
* <p>
@ -104,7 +112,8 @@ import static nl.komponents.kovenant.android.KovenantAndroid.stopKovenant;
*
* @author Moxie Marlinspike
*/
public class ApplicationContext extends Application implements DependencyInjector, DefaultLifecycleObserver {
@HiltAndroidApp
public class ApplicationContext extends Application implements DefaultLifecycleObserver {
public static final String PREFERENCES_NAME = "SecureSMS-Preferences";
@ -116,13 +125,17 @@ public class ApplicationContext extends Application implements DependencyInjecto
private JobManager jobManager;
private ReadReceiptManager readReceiptManager;
private ProfileManager profileManager;
private ObjectGraph objectGraph;
public MessageNotifier messageNotifier = null;
public Poller poller = null;
public Broadcaster broadcaster = null;
public SignalCommunicationModule communicationModule;
private Job firebaseInstanceIdJob;
private Handler conversationListNotificationHandler;
private PersistentLogger persistentLogger;
@Inject LokiAPIDatabase lokiAPIDatabase;
@Inject Storage storage;
@Inject MessageDataProvider messageDataProvider;
@Inject JobDatabase jobDatabase;
private volatile boolean isAppVisible;
@ -130,29 +143,37 @@ public class ApplicationContext extends Application implements DependencyInjecto
return (ApplicationContext) context.getApplicationContext();
}
public DatabaseComponent getDatabaseComponent() {
return EntryPoints.get(getApplicationContext(), DatabaseComponent.class);
}
public Handler getConversationListNotificationHandler() {
return this.conversationListNotificationHandler;
}
public PersistentLogger getPersistentLogger() {
return this.persistentLogger;
}
@Override
public void onCreate() {
DatabaseModule.init(this);
super.onCreate();
Log.i(TAG, "onCreate()");
startKovenant();
initializeSecurityProvider();
initializeLogging();
initializeCrashHandling();
initializeDependencyInjection();
NotificationChannels.create(this);
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
AppContext.INSTANCE.configureKovenant();
messageNotifier = new OptimizedMessageNotifier(new DefaultMessageNotifier());
broadcaster = new Broadcaster(this);
conversationListNotificationHandler = new Handler(Looper.getMainLooper());
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
LokiAPIDatabase apiDB = getDatabaseComponent().lokiAPIDatabase();
MessagingModuleConfiguration.Companion.configure(this,
DatabaseFactory.getStorage(this),
DatabaseFactory.getAttachmentProvider(this),
storage,
messageDataProvider,
()-> KeyPairUtilities.INSTANCE.getUserED25519KeyPair(this)
);
SnodeModule.Companion.configure(apiDB, broadcaster);
@ -210,13 +231,6 @@ public class ApplicationContext extends Application implements DependencyInjecto
super.onTerminate();
}
@Override
public void injectDependencies(Object object) {
if (object instanceof InjectableType) {
objectGraph.inject(object);
}
}
public void initializeLocaleParser() {
LocaleParser.Companion.configure(new LocaleParseHelper());
}
@ -276,7 +290,10 @@ public class ApplicationContext extends Application implements DependencyInjecto
}
private void initializeLogging() {
Log.initialize(new AndroidLogger());
if (persistentLogger == null) {
persistentLogger = new PersistentLogger(this);
}
Log.initialize(new AndroidLogger(), persistentLogger);
}
private void initializeCrashHandling() {
@ -290,16 +307,10 @@ public class ApplicationContext extends Application implements DependencyInjecto
.setJobFactories(JobManagerFactories.getJobFactories(this))
.setConstraintFactories(JobManagerFactories.getConstraintFactories(this))
.setConstraintObservers(JobManagerFactories.getConstraintObservers(this))
.setJobStorage(new FastJobStorage(DatabaseFactory.getJobDatabase(this)))
.setDependencyInjector(this)
.setJobStorage(new FastJobStorage(jobDatabase))
.build());
}
private void initializeDependencyInjection() {
communicationModule = new SignalCommunicationModule(this);
this.objectGraph = ObjectGraph.create(communicationModule);
}
private void initializeExpiringMessageManager() {
this.expiringMessageManager = new ExpiringMessageManager(this);
}

View File

@ -35,20 +35,19 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.Toolbar;
import org.session.libsession.utilities.DistributionTypes;
import org.thoughtcrime.securesms.components.SearchToolbar;
import org.session.libsession.utilities.Address;
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.session.libsession.utilities.DistributionTypes;
import org.session.libsession.utilities.ViewUtil;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.components.SearchToolbar;
import org.thoughtcrime.securesms.contacts.ContactSelectionListFragment;
import org.thoughtcrime.securesms.contacts.ContactSelectionListLoader.DisplayMode;
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.session.libsession.utilities.recipients.Recipient;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.session.libsession.utilities.ViewUtil;
import java.io.FileInputStream;
import java.io.IOException;
@ -251,7 +250,7 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
@Override
public void onContactSelected(String number) {
Recipient recipient = Recipient.from(this, Address.fromExternal(this, number), true);
long existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient);
long existingThread = DatabaseComponent.get(this).threadDatabase().getThreadIdIfExistsFor(recipient);
createConversation(existingThread, recipient.getAddress(), DistributionTypes.DEFAULT);
}

View File

@ -18,9 +18,9 @@ import org.session.libsignal.utilities.Log
import org.session.libsignal.utilities.guava.Optional
import org.thoughtcrime.securesms.database.AttachmentDatabase
import org.thoughtcrime.securesms.database.Database
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.MessagingDatabase
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.events.PartProgressEvent
import org.thoughtcrime.securesms.mms.MediaConstraints
import org.thoughtcrime.securesms.mms.PartAuthority
@ -31,25 +31,25 @@ import java.io.InputStream
class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), MessageDataProvider {
override fun getAttachmentStream(attachmentId: Long): SessionServiceAttachmentStream? {
val attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context)
val attachmentDatabase = DatabaseComponent.get(context).attachmentDatabase()
val databaseAttachment = attachmentDatabase.getAttachment(AttachmentId(attachmentId, 0)) ?: return null
return databaseAttachment.toAttachmentStream(context)
}
override fun getAttachmentPointer(attachmentId: Long): SessionServiceAttachmentPointer? {
val attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context)
val attachmentDatabase = DatabaseComponent.get(context).attachmentDatabase()
val databaseAttachment = attachmentDatabase.getAttachment(AttachmentId(attachmentId, 0)) ?: return null
return databaseAttachment.toAttachmentPointer()
}
override fun getSignalAttachmentStream(attachmentId: Long): SignalServiceAttachmentStream? {
val attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context)
val attachmentDatabase = DatabaseComponent.get(context).attachmentDatabase()
val databaseAttachment = attachmentDatabase.getAttachment(AttachmentId(attachmentId, 0)) ?: return null
return databaseAttachment.toSignalAttachmentStream(context)
}
override fun getScaledSignalAttachmentStream(attachmentId: Long): SignalServiceAttachmentStream? {
val database = DatabaseFactory.getAttachmentDatabase(context)
val database = DatabaseComponent.get(context).attachmentDatabase()
val databaseAttachment = database.getAttachment(AttachmentId(attachmentId, 0)) ?: return null
val mediaConstraints = MediaConstraints.getPushMediaConstraints()
val scaledAttachment = scaleAndStripExif(database, mediaConstraints, databaseAttachment) ?: return null
@ -57,45 +57,47 @@ class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper)
}
override fun getSignalAttachmentPointer(attachmentId: Long): SignalServiceAttachmentPointer? {
val attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context)
val attachmentDatabase = DatabaseComponent.get(context).attachmentDatabase()
val databaseAttachment = attachmentDatabase.getAttachment(AttachmentId(attachmentId, 0)) ?: return null
return databaseAttachment.toSignalAttachmentPointer()
}
override fun setAttachmentState(attachmentState: AttachmentState, attachmentId: AttachmentId, messageID: Long) {
val attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context)
val attachmentDatabase = DatabaseComponent.get(context).attachmentDatabase()
attachmentDatabase.setTransferState(messageID, attachmentId, attachmentState.value)
}
override fun getMessageForQuote(timestamp: Long, author: Address): Pair<Long, Boolean>? {
val messagingDatabase = DatabaseFactory.getMmsSmsDatabase(context)
val messagingDatabase = DatabaseComponent.get(context).mmsSmsDatabase()
val message = messagingDatabase.getMessageFor(timestamp, author)
return if (message != null) Pair(message.id, message.isMms) else null
}
override fun getAttachmentsAndLinkPreviewFor(mmsId: Long): List<Attachment> {
return DatabaseFactory.getAttachmentDatabase(context).getAttachmentsForMessage(mmsId)
return DatabaseComponent.get(context).attachmentDatabase().getAttachmentsForMessage(mmsId)
}
override fun getMessageBodyFor(timestamp: Long, author: String): String {
val messagingDatabase = DatabaseFactory.getMmsSmsDatabase(context)
val messagingDatabase = DatabaseComponent.get(context).mmsSmsDatabase()
return messagingDatabase.getMessageFor(timestamp, author)!!.body
}
override fun getAttachmentIDsFor(messageID: Long): List<Long> {
return DatabaseFactory.getAttachmentDatabase(context).getAttachmentsForMessage(messageID).mapNotNull {
return DatabaseComponent.get(context)
.attachmentDatabase()
.getAttachmentsForMessage(messageID).mapNotNull {
if (it.isQuote) return@mapNotNull null
it.attachmentId.rowId
}
}
override fun getLinkPreviewAttachmentIDFor(messageID: Long): Long? {
val message = DatabaseFactory.getMmsDatabase(context).getOutgoingMessage(messageID)
val message = DatabaseComponent.get(context).mmsDatabase().getOutgoingMessage(messageID)
return message.linkPreviews.firstOrNull()?.attachmentId?.rowId
}
override fun getIndividualRecipientForMms(mmsId: Long): Recipient? {
val mmsDb = DatabaseFactory.getMmsDatabase(context)
val mmsDb = DatabaseComponent.get(context).mmsDatabase()
val message = mmsDb.getMessage(mmsId).use {
mmsDb.readerFor(it).next
}
@ -103,7 +105,7 @@ class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper)
}
override fun insertAttachment(messageId: Long, attachmentId: AttachmentId, stream: InputStream) {
val attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context)
val attachmentDatabase = DatabaseComponent.get(context).attachmentDatabase()
attachmentDatabase.insertAttachmentsForPlaceholder(messageId, attachmentId, stream)
}
@ -112,7 +114,7 @@ class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper)
durationMs: Long,
threadId: Long
) {
val attachmentDb = DatabaseFactory.getAttachmentDatabase(context)
val attachmentDb = DatabaseComponent.get(context).attachmentDatabase()
attachmentDb.setAttachmentAudioExtras(DatabaseAttachmentAudioExtras(
attachmentId = attachmentId,
visualSamples = byteArrayOf(),
@ -121,20 +123,20 @@ class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper)
}
override fun isMmsOutgoing(mmsMessageId: Long): Boolean {
val mmsDb = DatabaseFactory.getMmsDatabase(context)
val mmsDb = DatabaseComponent.get(context).mmsDatabase()
return mmsDb.getMessage(mmsMessageId).use { cursor ->
mmsDb.readerFor(cursor).next
}.isOutgoing
}
override fun isOutgoingMessage(timestamp: Long): Boolean {
val smsDatabase = DatabaseFactory.getSmsDatabase(context)
val mmsDatabase = DatabaseFactory.getMmsDatabase(context)
val smsDatabase = DatabaseComponent.get(context).smsDatabase()
val mmsDatabase = DatabaseComponent.get(context).mmsDatabase()
return smsDatabase.isOutgoingMessage(timestamp) || mmsDatabase.isOutgoingMessage(timestamp)
}
override fun handleSuccessfulAttachmentUpload(attachmentId: Long, attachmentStream: SignalServiceAttachmentStream, attachmentKey: ByteArray, uploadResult: UploadResult) {
val database = DatabaseFactory.getAttachmentDatabase(context)
val database = DatabaseComponent.get(context).attachmentDatabase()
val databaseAttachment = getDatabaseAttachment(attachmentId) ?: return
val attachmentPointer = SignalServiceAttachmentPointer(uploadResult.id,
attachmentStream.contentType,
@ -152,35 +154,35 @@ class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper)
}
override fun handleFailedAttachmentUpload(attachmentId: Long) {
val database = DatabaseFactory.getAttachmentDatabase(context)
val database = DatabaseComponent.get(context).attachmentDatabase()
val databaseAttachment = getDatabaseAttachment(attachmentId) ?: return
database.handleFailedAttachmentUpload(databaseAttachment.attachmentId)
}
override fun getMessageID(serverID: Long): Long? {
val openGroupMessagingDatabase = DatabaseFactory.getLokiMessageDatabase(context)
val openGroupMessagingDatabase = DatabaseComponent.get(context).lokiMessageDatabase()
return openGroupMessagingDatabase.getMessageID(serverID)
}
override fun getMessageID(serverId: Long, threadId: Long): Pair<Long, Boolean>? {
val messageDB = DatabaseFactory.getLokiMessageDatabase(context)
val messageDB = DatabaseComponent.get(context).lokiMessageDatabase()
return messageDB.getMessageID(serverId, threadId)
}
override fun deleteMessage(messageID: Long, isSms: Boolean) {
val messagingDatabase: MessagingDatabase = if (isSms) DatabaseFactory.getSmsDatabase(context)
else DatabaseFactory.getMmsDatabase(context)
val messagingDatabase: MessagingDatabase = if (isSms) DatabaseComponent.get(context).smsDatabase()
else DatabaseComponent.get(context).mmsDatabase()
messagingDatabase.deleteMessage(messageID)
DatabaseFactory.getLokiMessageDatabase(context).deleteMessage(messageID, isSms)
DatabaseFactory.getLokiMessageDatabase(context).deleteMessageServerHash(messageID)
DatabaseComponent.get(context).lokiMessageDatabase().deleteMessage(messageID, isSms)
DatabaseComponent.get(context).lokiMessageDatabase().deleteMessageServerHash(messageID)
}
override fun updateMessageAsDeleted(timestamp: Long, author: String) {
val database = DatabaseFactory.getMmsSmsDatabase(context)
val database = DatabaseComponent.get(context).mmsSmsDatabase()
val address = Address.fromSerialized(author)
val message = database.getMessageFor(timestamp, address) ?: return
val messagingDatabase: MessagingDatabase = if (message.isMms) DatabaseFactory.getMmsDatabase(context)
else DatabaseFactory.getSmsDatabase(context)
val messagingDatabase: MessagingDatabase = if (message.isMms) DatabaseComponent.get(context).mmsDatabase()
else DatabaseComponent.get(context).smsDatabase()
messagingDatabase.markAsDeleted(message.id, message.isRead)
if (message.isOutgoing) {
messagingDatabase.deleteMessage(message.id)
@ -188,12 +190,12 @@ class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper)
}
override fun getServerHashForMessage(messageID: Long): String? {
val messageDB = DatabaseFactory.getLokiMessageDatabase(context)
val messageDB = DatabaseComponent.get(context).lokiMessageDatabase()
return messageDB.getMessageServerHash(messageID)
}
override fun getDatabaseAttachment(attachmentId: Long): DatabaseAttachment? {
val attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context)
val attachmentDatabase = DatabaseComponent.get(context).attachmentDatabase()
return attachmentDatabase.getAttachment(AttachmentId(attachmentId, 0))
}

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.backup;
package org.thoughtcrime.securesms.backup
import android.app.Activity
import android.app.Application
@ -24,17 +24,18 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import network.loki.messenger.R
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.BaseActionBarActivity
import org.thoughtcrime.securesms.backup.FullBackupImporter.DatabaseDowngradeException
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.util.setUpActionBarSessionLogo
import org.thoughtcrime.securesms.util.show
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.home.HomeActivity
import org.thoughtcrime.securesms.notifications.NotificationChannels
import org.thoughtcrime.securesms.util.BackupUtil
import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.home.HomeActivity
import org.thoughtcrime.securesms.util.setUpActionBarSessionLogo
import org.thoughtcrime.securesms.util.show
class BackupRestoreActivity : BaseActionBarActivity() {
@ -170,11 +171,11 @@ class BackupRestoreViewModel(application: Application): AndroidViewModel(applica
withContext(Dispatchers.IO) {
result = try {
val database = DatabaseFactory.getBackupDatabase(context)
val database = DatabaseComponent.get(context).openHelper().readableDatabase
FullBackupImporter.importFromUri(
context,
AttachmentSecretProvider.getInstance(context).getOrCreateAttachmentSecret(),
DatabaseFactory.getBackupDatabase(context),
database,
backupFile,
passphrase
)

View File

@ -7,13 +7,6 @@ import android.net.Uri
import androidx.annotation.WorkerThread
import net.sqlcipher.database.SQLiteDatabase
import org.greenrobot.eventbus.EventBus
import org.thoughtcrime.securesms.backup.BackupProtos.*
import org.thoughtcrime.securesms.crypto.AttachmentSecret
import org.thoughtcrime.securesms.crypto.ModernEncryptingPartOutputStream
import org.thoughtcrime.securesms.database.*
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.util.BackupUtil
import org.session.libsession.avatars.AvatarHelper
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId
import org.session.libsession.utilities.Address
@ -21,7 +14,13 @@ import org.session.libsession.utilities.Conversions
import org.session.libsession.utilities.Util
import org.session.libsignal.crypto.kdf.HKDFv3
import org.session.libsignal.utilities.ByteUtil
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.backup.BackupProtos.*
import org.thoughtcrime.securesms.crypto.AttachmentSecret
import org.thoughtcrime.securesms.crypto.ModernEncryptingPartOutputStream
import org.thoughtcrime.securesms.database.*
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.util.BackupUtil
import java.io.*
import java.security.InvalidAlgorithmParameterException
import java.security.InvalidKeyException
@ -179,14 +178,14 @@ object FullBackupImporter {
val where = AttachmentDatabase.MMS_ID + trimmedCondition
db.query(AttachmentDatabase.TABLE_NAME, columns, where, null, null, null, null).use { cursor ->
while (cursor != null && cursor.moveToNext()) {
DatabaseFactory.getAttachmentDatabase(context)
DatabaseComponent.get(context).attachmentDatabase()
.deleteAttachment(AttachmentId(cursor.getLong(0), cursor.getLong(1)))
}
}
db.query(ThreadDatabase.TABLE_NAME, arrayOf(ThreadDatabase.ID),
ThreadDatabase.EXPIRES_IN + " > 0", null, null, null, null).use { cursor ->
while (cursor != null && cursor.moveToNext()) {
DatabaseFactory.getThreadDatabase(context).update(cursor.getLong(0), false)
DatabaseComponent.get(context).threadDatabase().update(cursor.getLong(0), false)
}
}
}

View File

@ -15,8 +15,8 @@ import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.conversation.v2.components.ExpirationTimerView;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.thoughtcrime.securesms.util.DateUtils;
@ -117,8 +117,8 @@ public class ConversationItemFooter extends LinearLayout {
long id = messageRecord.getId();
boolean mms = messageRecord.isMms();
if (mms) DatabaseFactory.getMmsDatabase(getContext()).markExpireStarted(id);
else DatabaseFactory.getSmsDatabase(getContext()).markExpireStarted(id);
if (mms) DatabaseComponent.get(getContext()).mmsDatabase().markExpireStarted(id);
else DatabaseComponent.get(getContext()).smsDatabase().markExpireStarted(id);
expirationManager.scheduleDeletion(id, mms, messageRecord.getExpiresIn());
return null;

View File

@ -12,11 +12,9 @@ import kotlinx.android.synthetic.main.view_profile_picture.view.*
import network.loki.messenger.R
import org.session.libsession.avatars.ProfileContactPhoto
import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.messaging.mentions.MentionsManager
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.util.AvatarPlaceholderGenerator
@ -46,14 +44,14 @@ class ProfilePictureView : RelativeLayout {
// region Updating
fun update(recipient: Recipient, threadID: Long) {
fun getUserDisplayName(publicKey: String): String {
val contact = DatabaseFactory.getSessionContactDatabase(context).getContactWithSessionID(publicKey)
val contact = DatabaseComponent.get(context).sessionContactDatabase().getContactWithSessionID(publicKey)
return contact?.displayName(Contact.ContactContext.REGULAR) ?: publicKey
}
fun isOpenGroupWithProfilePicture(recipient: Recipient): Boolean {
return recipient.isOpenGroupRecipient && recipient.groupAvatarId != null
}
if (recipient.isGroupRecipient && !isOpenGroupWithProfilePicture(recipient)) {
val members = DatabaseFactory.getGroupDatabase(context)
val members = DatabaseComponent.get(context).groupDatabase()
.getGroupMemberAddresses(recipient.address.toGroupString(), true)
.sorted()
.take(2)

View File

@ -13,26 +13,28 @@ import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.annimon.stream.Stream;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import org.session.libsession.messaging.contacts.Contact;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.ThemeUtil;
import org.session.libsession.utilities.Util;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsession.utilities.recipients.RecipientModifiedListener;
import org.thoughtcrime.securesms.database.SessionContactDatabase;
import org.thoughtcrime.securesms.util.UiModeUtilities;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsession.utilities.recipients.RecipientModifiedListener;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.ThemeUtil;
import org.session.libsession.utilities.Util;
import org.thoughtcrime.securesms.util.UiModeUtilities;
import java.util.List;
@ -200,7 +202,7 @@ public class QuoteView extends FrameLayout implements RecipientModifiedListener
if (senderHexEncodedPublicKey.equalsIgnoreCase(TextSecurePreferences.getLocalNumber(getContext()))) {
quoteeDisplayName = TextSecurePreferences.getProfileName(getContext());
} else {
SessionContactDatabase contactDB = DatabaseFactory.getSessionContactDatabase(getContext());
SessionContactDatabase contactDB = DatabaseComponent.get(getContext()).sessionContactDatabase();
Contact contact = contactDB.getContactWithSessionID(senderHexEncodedPublicKey);
if (contact != null) {
Contact.ContactContext context = (this.conversationRecipient.isOpenGroupRecipient()) ? Contact.ContactContext.OPEN_GROUP : Contact.ContactContext.REGULAR;

View File

@ -2,15 +2,16 @@ package org.thoughtcrime.securesms.components;
import android.annotation.SuppressLint;
import android.content.Context;
import androidx.annotation.NonNull;
import org.session.libsession.messaging.messages.control.TypingIndicator;
import org.session.libsession.messaging.sending_receiving.MessageSender;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.util.SessionMetaProtocol;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsession.utilities.Util;
import org.session.libsession.utilities.recipients.Recipient;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.util.SessionMetaProtocol;
import java.util.HashMap;
import java.util.Map;
@ -76,7 +77,7 @@ public class TypingStatusSender {
}
private void sendTyping(long threadId, boolean typingStarted) {
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
ThreadDatabase threadDatabase = DatabaseComponent.get(context).threadDatabase();
Recipient recipient = threadDatabase.getRecipientForThreadId(threadId);
if (recipient == null) { return; }
if (!SessionMetaProtocol.shouldSendTypingIndicator(recipient.getAddress())) { return; }

View File

@ -21,17 +21,16 @@ import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.session.libsession.utilities.GroupRecord;
import org.session.libsession.utilities.TextSecurePreferences;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import java.util.LinkedList;
import java.util.List;
import network.loki.messenger.R;
import org.session.libsession.utilities.GroupRecord;
import org.session.libsession.utilities.TextSecurePreferences;
/**
* This class was originally a layer of indirection between
* ContactAccessorNewApi and ContactAccesorOldApi, which corresponded
@ -71,7 +70,7 @@ public class ContactAccessor {
GroupRecord record;
try {
reader = DatabaseFactory.getGroupDatabase(context).getGroupsFilteredByTitle(constraint);
reader = DatabaseComponent.get(context).groupDatabase().getGroupsFilteredByTitle(constraint);
while ((record = reader.getNext()) != null) {
numberList.add(record.getEncodedId());

View File

@ -21,22 +21,22 @@ import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MergeCursor;
import android.provider.ContactsContract;
import androidx.annotation.NonNull;
import androidx.loader.content.CursorLoader;
import android.text.TextUtils;
import network.loki.messenger.R;
import androidx.annotation.NonNull;
import androidx.loader.content.CursorLoader;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.session.libsession.utilities.GroupRecord;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.session.libsession.utilities.GroupRecord;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import java.util.ArrayList;
import java.util.List;
import network.loki.messenger.R;
/**
* CursorLoader that initializes a ContactsDatabase instance
*
@ -169,7 +169,7 @@ public class ContactsCursorLoader extends CursorLoader {
private Cursor getRecentConversationsCursor() {
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(getContext());
ThreadDatabase threadDatabase = DatabaseComponent.get(getContext()).threadDatabase();
MatrixCursor recentConversations = new MatrixCursor(CONTACT_PROJECTION, RECENT_CONVERSATION_MAX);
try (Cursor rawConversations = threadDatabase.getRecentConversationList(RECENT_CONVERSATION_MAX)) {
@ -208,7 +208,7 @@ public class ContactsCursorLoader extends CursorLoader {
private Cursor getGroupsCursor() {
MatrixCursor groupContacts = new MatrixCursor(CONTACT_PROJECTION);
try (GroupDatabase.Reader reader = DatabaseFactory.getGroupDatabase(getContext()).getGroupsFilteredByTitle(filter)) {
try (GroupDatabase.Reader reader = DatabaseComponent.get(getContext()).groupDatabase().getGroupsFilteredByTitle(filter)) {
GroupRecord groupRecord;
while ((groupRecord = reader.getNext()) != null) {
groupContacts.addRow(new Object[] { groupRecord.getTitle(),

View File

@ -9,10 +9,10 @@ import kotlinx.android.synthetic.main.view_conversation.view.profilePictureView
import kotlinx.android.synthetic.main.view_user.view.*
import network.loki.messenger.R
import org.session.libsession.messaging.contacts.Contact
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities
import org.thoughtcrime.securesms.mms.GlideRequests
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.mms.GlideRequests
class UserView : LinearLayout {
var openGroupThreadID: Long = -1 // FIXME: This is a bit ugly
@ -50,10 +50,10 @@ class UserView : LinearLayout {
// region Updating
fun bind(user: Recipient, glide: GlideRequests, actionIndicator: ActionIndicator, isSelected: Boolean = false) {
fun getUserDisplayName(publicKey: String): String {
val contact = DatabaseFactory.getSessionContactDatabase(context).getContactWithSessionID(publicKey)
val contact = DatabaseComponent.get(context).sessionContactDatabase().getContactWithSessionID(publicKey)
return contact?.displayName(Contact.ContactContext.REGULAR) ?: publicKey
}
val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(user)
val threadID = DatabaseComponent.get(context).threadDatabase().getOrCreateThreadIdFor(user)
MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded(threadID, context) // FIXME: This is a bad place to do this
val address = user.address.serialize()
profilePictureView.glide = glide

View File

@ -30,6 +30,7 @@ import androidx.loader.content.Loader
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.annimon.stream.Stream
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.android.synthetic.main.activity_conversation_v2.*
import kotlinx.android.synthetic.main.activity_conversation_v2.view.*
import kotlinx.android.synthetic.main.activity_conversation_v2_action_bar.*
@ -91,8 +92,7 @@ import org.thoughtcrime.securesms.conversation.v2.search.SearchViewModel
import org.thoughtcrime.securesms.conversation.v2.utilities.*
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.crypto.MnemonicUtilities
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.DraftDatabase
import org.thoughtcrime.securesms.database.*
import org.thoughtcrime.securesms.database.DraftDatabase.Drafts
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
@ -109,6 +109,7 @@ import org.thoughtcrime.securesms.permissions.Permissions
import org.thoughtcrime.securesms.util.*
import java.util.*
import java.util.concurrent.ExecutionException
import javax.inject.Inject
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.set
@ -117,11 +118,26 @@ import kotlin.math.*
// Some things that seemingly belong to the input bar (e.g. the voice message recording UI) are actually
// part of the conversation activity layout. This is just because it makes the layout a lot simpler. The
// price we pay is a bit of back and forth between the input bar and the conversation activity.
@AndroidEntryPoint
class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDelegate,
InputBarRecordingViewDelegate, AttachmentManager.AttachmentListener, ActivityDispatcher,
ConversationActionModeCallbackDelegate, VisibleMessageContentViewDelegate, RecipientModifiedListener,
SearchBottomBar.EventListener, VoiceMessageViewDelegate {
@Inject lateinit var threadDb: ThreadDatabase
@Inject lateinit var mmsSmsDb: MmsSmsDatabase
@Inject lateinit var draftDb: DraftDatabase
@Inject lateinit var lokiThreadDb: LokiThreadDatabase
@Inject lateinit var sessionContactDb: SessionContactDatabase
@Inject lateinit var groupDb: GroupDatabase
@Inject lateinit var lokiApiDb: LokiAPIDatabase
@Inject lateinit var recipientDb: RecipientDatabase
@Inject lateinit var smsDb: SmsDatabase
@Inject lateinit var mmsDb: MmsDatabase
@Inject lateinit var lokiMessageDb: LokiMessageDatabase
private val screenWidth = Resources.getSystem().displayMetrics.widthPixels
private var linkPreviewViewModel: LinkPreviewViewModel? = null
private var threadID: Long = -1
@ -165,7 +181,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
}
private val adapter by lazy {
val cursor = DatabaseFactory.getMmsSmsDatabase(this).getConversation(threadID)
val cursor = mmsSmsDb.getConversation(threadID)
val adapter = ConversationAdapter(
this,
cursor,
@ -185,7 +201,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
}
private val thread by lazy {
DatabaseFactory.getThreadDatabase(this).getRecipientForThreadId(threadID)!!
threadDb.getRecipientForThreadId(threadID)!!
}
private val glide by lazy { GlideApp.with(this) }
@ -216,14 +232,13 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
super.onCreate(savedInstanceState, isReady)
setContentView(R.layout.activity_conversation_v2)
var threadID = intent.getLongExtra(THREAD_ID, -1L)
threadID = intent.getLongExtra(THREAD_ID, -1L)
if (threadID == -1L) {
val address = intent.getParcelableExtra<Address>(ADDRESS) ?: return finish()
val recipient = Recipient.from(this, address, false)
threadID = DatabaseFactory.getThreadDatabase(this).getOrCreateThreadIdFor(recipient)
threadID = threadDb.getOrCreateThreadIdFor(recipient)
}
this.threadID = threadID
val thread = DatabaseFactory.getThreadDatabase(this).getRecipientForThreadId(threadID)
val thread = threadDb.getRecipientForThreadId(threadID)
if (thread == null) {
Toast.makeText(this, "This thread has been deleted.", Toast.LENGTH_LONG).show()
return finish()
@ -242,7 +257,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
conversationRecyclerView.smoothScrollToPosition(0)
}
}
unreadCount = DatabaseFactory.getMmsSmsDatabase(this).getUnreadCount(threadID)
unreadCount = mmsSmsDb.getUnreadCount(threadID)
updateUnreadCountIndicator()
setUpTypingObserver()
setUpRecipientObserver()
@ -254,7 +269,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
scrollToFirstUnreadMessageIfNeeded()
showOrHideInputIfNeeded()
if (this.thread.isOpenGroupRecipient) {
val openGroup = DatabaseFactory.getLokiThreadDatabase(this).getOpenGroupChat(threadID)
val openGroup = lokiThreadDb.getOpenGroupChat(threadID)
if (openGroup == null) {
Toast.makeText(this, "This thread has been deleted.", Toast.LENGTH_LONG).show()
return finish()
@ -384,16 +399,15 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
val dataTextExtra = intent.getCharSequenceExtra(Intent.EXTRA_TEXT) ?: ""
inputBar.text = dataTextExtra.toString()
} else {
val draftDB = DatabaseFactory.getDraftDatabase(this)
val drafts = draftDB.getDrafts(threadID)
draftDB.clearDrafts(threadID)
val drafts = draftDb.getDrafts(threadID)
draftDb.clearDrafts(threadID)
val text = drafts.find { it.type == DraftDatabase.Draft.TEXT }?.value ?: return
inputBar.text = text
}
}
private fun addOpenGroupGuidelinesIfNeeded() {
val openGroup = DatabaseFactory.getLokiThreadDatabase(this).getOpenGroupChat(threadID) ?: return
val openGroup = lokiThreadDb.getOpenGroupChat(threadID) ?: return
val isOxenHostedOpenGroup = openGroup.room == "session" || openGroup.room == "oxen"
|| openGroup.room == "lokinet" || openGroup.room == "crypto"
if (!isOxenHostedOpenGroup) { return }
@ -427,13 +441,13 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
}
private fun getLatestOpenGroupInfoIfNeeded() {
val openGroup = DatabaseFactory.getLokiThreadDatabase(this).getOpenGroupChat(threadID) ?: return
val openGroup = lokiThreadDb.getOpenGroupChat(threadID) ?: return
OpenGroupAPIV2.getMemberCount(openGroup.room, openGroup.server).successUi { updateSubtitle() }
}
private fun setUpBlockedBanner() {
if (thread.isGroupRecipient) { return }
val contactDB = DatabaseFactory.getSessionContactDatabase(this)
val contactDB = sessionContactDb
val sessionID = thread.address.toString()
val contact = contactDB.getContactWithSessionID(sessionID)
val name = contact?.displayName(Contact.ContactContext.REGULAR) ?: sessionID
@ -461,7 +475,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
}
private fun scrollToFirstUnreadMessageIfNeeded() {
val lastSeenTimestamp = DatabaseFactory.getThreadDatabase(this).getLastSeenAndHasSent(threadID).first()
val lastSeenTimestamp = threadDb.getLastSeenAndHasSent(threadID).first()
val lastSeenItemPosition = adapter.findLastSeenItemPosition(lastSeenTimestamp) ?: return
if (lastSeenItemPosition <= 3) { return }
conversationRecyclerView.scrollToPosition(lastSeenItemPosition)
@ -492,7 +506,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
private fun showOrHideInputIfNeeded() {
if (thread.isClosedGroupRecipient) {
val group = DatabaseFactory.getGroupDatabase(this).getGroup(thread.address.toGroupString()).orNull()
val group = groupDb.getGroup(thread.address.toGroupString()).orNull()
val isActive = (group?.isActive == true)
inputBar.showInput = isActive
} else {
@ -501,7 +515,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
}
private fun markAllAsRead() {
val messages = DatabaseFactory.getThreadDatabase(this).setRead(threadID, true)
val messages = threadDb.setRead(threadID, true)
if (thread.isGroupRecipient) {
for (message in messages) {
MarkReadReceiver.scheduleDeletion(this, message.expirationInfo)
@ -733,9 +747,9 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
conversationSubtitleView.text = getString(R.string.ConversationActivity_muted_forever)
}
} else if (thread.isGroupRecipient) {
val openGroup = DatabaseFactory.getLokiThreadDatabase(this).getOpenGroupChat(threadID)
val openGroup = lokiThreadDb.getOpenGroupChat(threadID)
if (openGroup != null) {
val userCount = DatabaseFactory.getLokiAPIDatabase(this).getUserCount(openGroup.room, openGroup.server) ?: 0
val userCount = lokiApiDb.getUserCount(openGroup.room, openGroup.server) ?: 0
conversationSubtitleView.text = getString(R.string.ConversationActivity_member_count, userCount)
} else {
conversationSubtitleView.isVisible = false
@ -867,7 +881,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
private fun unblock() {
if (!thread.isContactRecipient) { return }
DatabaseFactory.getRecipientDatabase(this).setBlocked(thread, false)
recipientDb.setBlocked(thread, false)
}
private fun handleMentionSelected(mention: Mention) {
@ -937,7 +951,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
currentMentionStartIndex = -1
mentions.clear()
// Put the message in the database
message.id = DatabaseFactory.getSmsDatabase(this).insertMessageOutbox(threadID, outgoingTextMessage, false, message.sentTimestamp!!) { }
message.id = smsDb.insertMessageOutbox(threadID, outgoingTextMessage, false, message.sentTimestamp!!) { }
// Send it
MessageSender.send(message, thread.address)
// Send a typing stopped message
@ -968,7 +982,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
// Reset attachments button if needed
if (isShowingAttachmentOptions) { toggleAttachmentOptions() }
// Put the message in the database
message.id = DatabaseFactory.getMmsDatabase(this).insertMessageOutbox(outgoingTextMessage, threadID, false) { }
message.id = mmsDb.insertMessageOutbox(outgoingTextMessage, threadID, false) { }
// Send it
MessageSender.send(message, thread.address, attachments, quote, linkPreview)
// Send a typing stopped message
@ -1070,7 +1084,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
val extras = intent?.extras ?: return
if (!intent.hasExtra(SelectContactsActivity.selectedContactsKey)) { return }
val selectedContacts = extras.getStringArray(selectedContactsKey)!!
val openGroup = DatabaseFactory.getLokiThreadDatabase(this).getOpenGroupChat(threadID)
val openGroup = lokiThreadDb.getOpenGroupChat(threadID)
for (contact in selectedContacts) {
val recipient = Recipient.from(this, fromSerialized(contact), true)
val message = VisibleMessage()
@ -1080,7 +1094,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
openGroupInvitation.url = openGroup!!.joinURL
message.openGroupInvitation = openGroupInvitation
val outgoingTextMessage = OutgoingTextMessage.fromOpenGroupInvitation(openGroupInvitation, recipient, message.sentTimestamp)
DatabaseFactory.getSmsDatabase(this).insertMessageOutbox(-1, outgoingTextMessage, message.sentTimestamp!!)
smsDb.insertMessageOutbox(-1, outgoingTextMessage, message.sentTimestamp!!)
MessageSender.send(message, recipient.address)
}
}
@ -1166,10 +1180,9 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
MessageSender.send(unsendRequest, thread.address)
}
val messageDataProvider = MessagingModuleConfiguration.shared.messageDataProvider
val messageDB = DatabaseFactory.getLokiMessageDatabase(this@ConversationActivityV2)
val openGroup = DatabaseFactory.getLokiThreadDatabase(this).getOpenGroupChat(threadID)
val openGroup = lokiThreadDb.getOpenGroupChat(threadID)
if (openGroup != null) {
messageDB.getServerID(message.id, !message.isMms)?.let { messageServerID ->
lokiMessageDb.getServerID(message.id, !message.isMms)?.let { messageServerID ->
OpenGroupAPIV2.deleteMessage(messageServerID, openGroup.room, openGroup.server)
.success {
messageDataProvider.deleteMessage(message.id, !message.isMms)
@ -1194,17 +1207,16 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
fun deleteMessagesWithoutUnsendRequest(messages: Set<MessageRecord>) {
val messageCount = messages.size
val messageDataProvider = MessagingModuleConfiguration.shared.messageDataProvider
val messageDB = DatabaseFactory.getLokiMessageDatabase(this@ConversationActivityV2)
val builder = AlertDialog.Builder(this)
builder.setTitle(resources.getQuantityString(R.plurals.ConversationFragment_delete_selected_messages, messageCount, messageCount))
builder.setMessage(resources.getQuantityString(R.plurals.ConversationFragment_this_will_permanently_delete_all_n_selected_messages, messageCount, messageCount))
builder.setCancelable(true)
val openGroup = DatabaseFactory.getLokiThreadDatabase(this).getOpenGroupChat(threadID)
val openGroup = lokiThreadDb.getOpenGroupChat(threadID)
builder.setPositiveButton(R.string.delete) { _, _ ->
if (openGroup != null) {
val messageServerIDs = mutableMapOf<Long, MessageRecord>()
for (message in messages) {
val messageServerID = messageDB.getServerID(message.id, !message.isMms) ?: continue
val messageServerID = lokiMessageDb.getServerID(message.id, !message.isMms) ?: continue
messageServerIDs[messageServerID] = message
}
for ((messageServerID, message) in messageServerIDs) {
@ -1218,9 +1230,9 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
} else {
for (message in messages) {
if (message.isMms) {
DatabaseFactory.getMmsDatabase(this@ConversationActivityV2).deleteMessage(message.id)
mmsDb.deleteMessage(message.id)
} else {
DatabaseFactory.getSmsDatabase(this@ConversationActivityV2).deleteMessage(message.id)
smsDb.deleteMessage(message.id)
}
}
}
@ -1239,7 +1251,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
return
}
val allSentByCurrentUser = messages.all { it.isOutgoing }
val allHasHash = messages.all { DatabaseFactory.getLokiMessageDatabase(this@ConversationActivityV2).getMessageServerHash(it.id) != null }
val allHasHash = messages.all { lokiMessageDb.getMessageServerHash(it.id) != null }
if (thread.isOpenGroupRecipient) {
val messageCount = messages.size
val builder = AlertDialog.Builder(this)
@ -1305,7 +1317,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
builder.setTitle(R.string.ConversationFragment_ban_selected_user)
builder.setMessage("This will ban the selected user from this room. It won't ban them from other rooms.")
builder.setCancelable(true)
val openGroup = DatabaseFactory.getLokiThreadDatabase(this).getOpenGroupChat(threadID)!!
val openGroup = lokiThreadDb.getOpenGroupChat(threadID)!!
builder.setPositiveButton(R.string.ban) { _, _ ->
OpenGroupAPIV2.ban(sessionID, openGroup.room, openGroup.server).successUi {
Toast.makeText(this@ConversationActivityV2, "Successfully banned user", Toast.LENGTH_LONG).show()
@ -1327,7 +1339,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
builder.setTitle(R.string.ConversationFragment_ban_selected_user)
builder.setMessage("This will ban the selected user from this room and delete all messages sent by them. It won't ban them from other rooms or delete the messages they sent there.")
builder.setCancelable(true)
val openGroup = DatabaseFactory.getLokiThreadDatabase(this).getOpenGroupChat(threadID)!!
val openGroup = lokiThreadDb.getOpenGroupChat(threadID)!!
builder.setPositiveButton(R.string.ban) { _, _ ->
OpenGroupAPIV2.banAndDeleteAll(sessionID, openGroup.room, openGroup.server).successUi {
Toast.makeText(this@ConversationActivityV2, "Successfully banned user and deleted all their messages", Toast.LENGTH_LONG).show()
@ -1468,8 +1480,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
if (text.isEmpty()) { return }
val drafts = Drafts()
drafts.add(DraftDatabase.Draft(DraftDatabase.Draft.TEXT, text))
val draftDB = DatabaseFactory.getDraftDatabase(this)
draftDB.insertDrafts(threadID, drafts)
draftDb.insertDrafts(threadID, drafts)
}
// endregion
@ -1502,7 +1513,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
private fun jumpToMessage(author: Address, timestamp: Long, onMessageNotFound: Runnable?) {
SimpleTask.run(lifecycle, {
DatabaseFactory.getMmsSmsDatabase(this).getMessagePositionInConversation(threadID, timestamp, author)
mmsSmsDb.getMessagePositionInConversation(threadID, timestamp, author)
}) { p: Int -> moveToMessagePosition(p, onMessageNotFound) }
}

View File

@ -11,15 +11,15 @@ import org.thoughtcrime.securesms.conversation.v2.messages.ControlMessageView
import org.thoughtcrime.securesms.conversation.v2.messages.VisibleMessageContentViewDelegate
import org.thoughtcrime.securesms.conversation.v2.messages.VisibleMessageView
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.mms.GlideRequests
class ConversationAdapter(context: Context, cursor: Cursor, private val onItemPress: (MessageRecord, Int, VisibleMessageView, MotionEvent) -> Unit,
private val onItemSwipeToReply: (MessageRecord, Int) -> Unit, private val onItemLongPress: (MessageRecord, Int) -> Unit,
private val glide: GlideRequests)
: CursorRecyclerViewAdapter<ViewHolder>(context, cursor) {
private val messageDB = DatabaseFactory.getMmsSmsDatabase(context)
private val messageDB = DatabaseComponent.get(context).mmsSmsDatabase()
var selectedItems = mutableSetOf<MessageRecord>()
private var searchQuery: String? = null
var visibleMessageContentViewDelegate: VisibleMessageContentViewDelegate? = null

View File

@ -2,12 +2,12 @@ package org.thoughtcrime.securesms.conversation.v2
import android.content.Context
import android.database.Cursor
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.util.AbstractCursorLoader
class ConversationLoader(private val threadID: Long, context: Context) : AbstractCursorLoader(context) {
override fun getCursor(): Cursor {
return DatabaseFactory.getMmsSmsDatabase(context).getConversation(threadID)
return DatabaseComponent.get(context).mmsSmsDatabase().getConversation(threadID)
}
}

View File

@ -2,31 +2,18 @@ package org.thoughtcrime.securesms.conversation.v2
import android.os.Bundle
import android.view.View
import android.widget.LinearLayout
import androidx.annotation.DimenRes
import kotlinx.android.synthetic.main.activity_conversation_v2_action_bar.*
import kotlinx.android.synthetic.main.activity_message_detail.*
import network.loki.messenger.R
import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.messaging.messages.visible.LinkPreview
import org.session.libsession.messaging.messages.visible.OpenGroupInvitation
import org.session.libsession.messaging.messages.visible.Quote
import org.session.libsession.messaging.messages.visible.VisibleMessage
import org.session.libsession.messaging.sending_receiving.MessageSender
import org.session.libsession.messaging.utilities.UpdateMessageData
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.ExpirationUtil
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.conversation.v2.utilities.ResendMessageUtilities
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.util.DateUtils
import java.text.SimpleDateFormat
import java.util.*
import kotlin.math.roundToInt
class MessageDetailActivity: PassphraseRequiredActionBarActivity() {
@ -48,7 +35,7 @@ class MessageDetailActivity: PassphraseRequiredActionBarActivity() {
// We only show this screen for messages fail to send,
// so the author of the messages must be the current user.
val author = Address.fromSerialized(TextSecurePreferences.getLocalNumber(this)!!)
messageRecord = DatabaseFactory.getMmsSmsDatabase (this).getMessageFor(timestamp, author)
messageRecord = DatabaseComponent.get(this).mmsSmsDatabase().getMessageFor(timestamp, author)
updateContent()
resend_button.setOnClickListener {
ResendMessageUtilities.resend(messageRecord!!)
@ -61,7 +48,7 @@ class MessageDetailActivity: PassphraseRequiredActionBarActivity() {
val dateFormatter: SimpleDateFormat = DateUtils.getDetailedDateFormatter(this, dateLocale)
sent_time.text = dateFormatter.format(Date(messageRecord!!.dateSent))
val errorMessage = DatabaseFactory.getLokiMessageDatabase(this).getErrorMessage(messageRecord!!.getId()) ?: "Message failed to send."
val errorMessage = DatabaseComponent.get(this).lokiMessageDatabase().getErrorMessage(messageRecord!!.getId()) ?: "Message failed to send."
error_message.text = errorMessage
if (messageRecord!!.getExpiresIn() <= 0 || messageRecord!!.getExpireStarted() <= 0) {

View File

@ -7,10 +7,10 @@ import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.ListView
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.util.toPx
import org.thoughtcrime.securesms.mms.GlideRequests
import org.session.libsession.messaging.mentions.Mention
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.util.toPx
class MentionCandidateSelectionView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : ListView(context, attrs, defStyleAttr) {
private var mentionCandidates = listOf<Mention>()
@ -68,7 +68,7 @@ class MentionCandidateSelectionView(context: Context, attrs: AttributeSet?, defS
}
fun show(mentionCandidates: List<Mention>, threadID: Long) {
val openGroup = DatabaseFactory.getLokiThreadDatabase(context).getOpenGroupChat(threadID)
val openGroup = DatabaseComponent.get(context).lokiThreadDatabase().getOpenGroupChat(threadID)
if (openGroup != null) {
openGroupServer = openGroup.server
openGroupRoom = openGroup.room

View File

@ -7,19 +7,18 @@ import android.text.style.StyleSpan
import android.view.LayoutInflater
import androidx.appcompat.app.AlertDialog
import kotlinx.android.synthetic.main.dialog_blocked.view.*
import kotlinx.android.synthetic.main.dialog_blocked.view.cancelButton
import network.loki.messenger.R
import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
/** Shown upon sending a message to a user that's blocked. */
class BlockedDialog(private val recipient: Recipient) : BaseDialog() {
override fun setContentView(builder: AlertDialog.Builder) {
val contentView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_blocked, null)
val contactDB = DatabaseFactory.getSessionContactDatabase(requireContext())
val contactDB = DatabaseComponent.get(requireContext()).sessionContactDatabase()
val sessionID = recipient.address.toString()
val contact = contactDB.getContactWithSessionID(sessionID)
val name = contact?.displayName(Contact.ContactContext.REGULAR) ?: sessionID
@ -36,7 +35,7 @@ class BlockedDialog(private val recipient: Recipient) : BaseDialog() {
}
private fun unblock() {
DatabaseFactory.getRecipientDatabase(requireContext()).setBlocked(recipient, false)
DatabaseComponent.get(requireContext()).recipientDatabase().setBlocked(recipient, false)
dismiss()
}
}

View File

@ -6,6 +6,7 @@ import android.text.SpannableStringBuilder
import android.text.style.StyleSpan
import android.view.LayoutInflater
import androidx.appcompat.app.AlertDialog
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.android.synthetic.main.dialog_download.view.*
import network.loki.messenger.R
import org.session.libsession.messaging.contacts.Contact
@ -13,15 +14,19 @@ import org.session.libsession.messaging.jobs.AttachmentDownloadJob
import org.session.libsession.messaging.jobs.JobQueue
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.SessionContactDatabase
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import javax.inject.Inject
/** Shown when receiving media from a contact for the first time, to confirm that
* they are to be trusted and files sent by them are to be downloaded. */
@AndroidEntryPoint
class DownloadDialog(private val recipient: Recipient) : BaseDialog() {
@Inject lateinit var contactDB: SessionContactDatabase
override fun setContentView(builder: AlertDialog.Builder) {
val contentView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_download, null)
val contactDB = DatabaseFactory.getSessionContactDatabase(requireContext())
val sessionID = recipient.address.toString()
val contact = contactDB.getContactWithSessionID(sessionID)
val name = contact?.displayName(Contact.ContactContext.REGULAR) ?: sessionID
@ -38,10 +43,9 @@ class DownloadDialog(private val recipient: Recipient) : BaseDialog() {
}
private fun trust() {
val contactDB = DatabaseFactory.getSessionContactDatabase(requireContext())
val sessionID = recipient.address.toString()
val contact = contactDB.getContactWithSessionID(sessionID) ?: return
val threadID = DatabaseFactory.getThreadDatabase(requireContext()).getThreadIdIfExistsFor(recipient)
val threadID = DatabaseComponent.get(requireContext()).threadDatabase().getThreadIdIfExistsFor(recipient)
contactDB.setContactIsTrusted(contact, true, threadID)
JobQueue.shared.resumePendingJobs(AttachmentDownloadJob.KEY)
dismiss()

View File

@ -7,11 +7,14 @@ import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.ListView
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.util.toPx
import org.thoughtcrime.securesms.mms.GlideRequests
import dagger.hilt.android.AndroidEntryPoint
import org.session.libsession.messaging.mentions.Mention
import org.thoughtcrime.securesms.database.LokiThreadDatabase
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.util.toPx
import javax.inject.Inject
@AndroidEntryPoint
class MentionCandidatesView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : ListView(context, attrs, defStyleAttr) {
private var candidates = listOf<Mention>()
set(newValue) { field = newValue; snAdapter.candidates = newValue }
@ -23,6 +26,8 @@ class MentionCandidatesView(context: Context, attrs: AttributeSet?, defStyleAttr
set(newValue) { field = newValue; snAdapter.openGroupRoom = openGroupRoom }
var onCandidateSelected: ((Mention) -> Unit)? = null
@Inject lateinit var threadDb: LokiThreadDatabase
private val snAdapter by lazy { Adapter(context) }
private class Adapter(private val context: Context) : BaseAdapter() {
@ -60,7 +65,7 @@ class MentionCandidatesView(context: Context, attrs: AttributeSet?, defStyleAttr
}
fun show(candidates: List<Mention>, threadID: Long) {
val openGroup = DatabaseFactory.getLokiThreadDatabase(context).getOpenGroupChat(threadID)
val openGroup = threadDb.getOpenGroupChat(threadID)
if (openGroup != null) {
openGroupServer = openGroup.server
openGroupRoom = openGroup.room

View File

@ -9,9 +9,9 @@ import org.session.libsession.messaging.open_groups.OpenGroupAPIV2
import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.conversation.v2.ConversationAdapter
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
class ConversationActionModeCallback(private val adapter: ConversationAdapter, private val threadID: Long,
private val context: Context) : ActionMode.Callback {
@ -31,8 +31,8 @@ class ConversationActionModeCallback(private val adapter: ConversationAdapter, p
val hasText = selectedItems.any { it.body.isNotEmpty() }
if (selectedItems.isEmpty()) { return }
val firstMessage = selectedItems.iterator().next()
val openGroup = DatabaseFactory.getLokiThreadDatabase(context).getOpenGroupChat(threadID)
val thread = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadID)!!
val openGroup = DatabaseComponent.get(context).lokiThreadDatabase().getOpenGroupChat(threadID)
val thread = DatabaseComponent.get(context).threadDatabase().getRecipientForThreadId(threadID)!!
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
fun userCanDeleteSelectedItems(): Boolean {
val allSentByCurrentUser = selectedItems.all { it.isOutgoing }

View File

@ -39,7 +39,7 @@ import org.thoughtcrime.securesms.*
import org.thoughtcrime.securesms.contacts.SelectContactsActivity
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.conversation.v2.utilities.NotificationUtils
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.groups.EditClosedGroupActivity
import org.thoughtcrime.securesms.groups.EditClosedGroupActivity.Companion.groupIDKey
import org.thoughtcrime.securesms.util.BitmapUtil
@ -214,11 +214,11 @@ object ConversationMenuHelper {
private fun showExpiringMessagesDialog(context: Context, thread: Recipient) {
if (thread.isClosedGroupRecipient) {
val group = DatabaseFactory.getGroupDatabase(context).getGroup(thread.address.toGroupString()).orNull()
val group = DatabaseComponent.get(context).groupDatabase().getGroup(thread.address.toGroupString()).orNull()
if (group?.isActive == false) { return }
}
ExpirationDialog.show(context, thread.expireMessages) { expirationTime: Int ->
DatabaseFactory.getRecipientDatabase(context).setExpireMessages(thread, expirationTime)
DatabaseComponent.get(context).recipientDatabase().setExpireMessages(thread, expirationTime)
val message = ExpirationTimerUpdate(expirationTime)
message.recipient = thread.address.serialize()
message.sentTimestamp = System.currentTimeMillis()
@ -239,7 +239,7 @@ object ConversationMenuHelper {
.setMessage(message)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.ConversationActivity_unblock) { _, _ ->
DatabaseFactory.getRecipientDatabase(context)
DatabaseComponent.get(context).recipientDatabase()
.setBlocked(thread, false)
}.show()
}
@ -253,7 +253,7 @@ object ConversationMenuHelper {
.setMessage(message)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.RecipientPreferenceActivity_block) { _, _ ->
DatabaseFactory.getRecipientDatabase(context)
DatabaseComponent.get(context).recipientDatabase()
.setBlocked(thread, true)
}.show()
}
@ -281,7 +281,7 @@ object ConversationMenuHelper {
val builder = AlertDialog.Builder(context)
builder.setTitle(context.resources.getString(R.string.ConversationActivity_leave_group))
builder.setCancelable(true)
val group = DatabaseFactory.getGroupDatabase(context).getGroup(thread.address.toGroupString()).orNull()
val group = DatabaseComponent.get(context).groupDatabase().getGroup(thread.address.toGroupString()).orNull()
val admins = group.admins
val sessionID = TextSecurePreferences.getLocalNumber(context)
val isCurrentUserAdmin = admins.any { it.toString() == sessionID }
@ -296,7 +296,7 @@ object ConversationMenuHelper {
var isClosedGroup: Boolean
try {
groupPublicKey = doubleDecodeGroupID(thread.address.toString()).toHexString()
isClosedGroup = DatabaseFactory.getLokiAPIDatabase(context).isClosedGroup(groupPublicKey)
isClosedGroup = DatabaseComponent.get(context).lokiAPIDatabase().isClosedGroup(groupPublicKey)
} catch (e: IOException) {
groupPublicKey = null
isClosedGroup = false
@ -323,18 +323,18 @@ object ConversationMenuHelper {
}
private fun unmute(context: Context, thread: Recipient) {
DatabaseFactory.getRecipientDatabase(context).setMuted(thread, 0)
DatabaseComponent.get(context).recipientDatabase().setMuted(thread, 0)
}
private fun mute(context: Context, thread: Recipient) {
MuteDialog.show(context) { until: Long ->
DatabaseFactory.getRecipientDatabase(context).setMuted(thread, until)
DatabaseComponent.get(context).recipientDatabase().setMuted(thread, until)
}
}
private fun setNotifyType(context: Context, thread: Recipient) {
NotificationUtils.showNotifyDialog(context, thread) { notifyType ->
DatabaseFactory.getRecipientDatabase(context).setNotifyType(thread, notifyType)
DatabaseComponent.get(context).recipientDatabase().setNotifyType(thread, notifyType)
}
}

View File

@ -10,18 +10,20 @@ import androidx.annotation.ColorInt
import androidx.core.content.res.ResourcesCompat
import androidx.core.text.toSpannable
import androidx.core.view.isVisible
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.android.synthetic.main.view_quote.view.*
import network.loki.messenger.R
import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities
import org.thoughtcrime.securesms.conversation.v2.utilities.TextUtilities
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.util.*
import org.thoughtcrime.securesms.database.SessionContactDatabase
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.mms.SlideDeck
import org.thoughtcrime.securesms.util.MediaUtil
import org.thoughtcrime.securesms.util.UiModeUtilities
import org.thoughtcrime.securesms.util.toPx
import javax.inject.Inject
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
@ -32,8 +34,11 @@ import kotlin.math.roundToInt
// • Quoted images and videos in both private chats and group chats
// • Quoted voice messages and documents in both private chats and group chats
// • All of the above in both dark mode and light mode
@AndroidEntryPoint
class QuoteView : LinearLayout {
@Inject lateinit var contactDb: SessionContactDatabase
private lateinit var mode: Mode
private val vPadding by lazy { toPx(6, resources) }
var delegate: QuoteViewDelegate? = null
@ -107,14 +112,13 @@ class QuoteView : LinearLayout {
fun bind(authorPublicKey: String, body: String?, attachments: SlideDeck?, thread: Recipient,
isOutgoingMessage: Boolean, maxContentWidth: Int, isOpenGroupInvitation: Boolean, threadID: Long,
isOriginalMissing: Boolean, glide: GlideRequests) {
val contactDB = DatabaseFactory.getSessionContactDatabase(context)
// Reduce the max body text view line count to 2 if this is a group thread because
// we'll be showing the author text view and we don't want the overall quote view height
// to get too big.
quoteViewBodyTextView.maxLines = if (thread.isGroupRecipient) 2 else 3
// Author
if (thread.isGroupRecipient) {
val author = contactDB.getContactWithSessionID(authorPublicKey)
val author = contactDb.getContactWithSessionID(authorPublicKey)
val authorDisplayName = author?.displayName(Contact.contextForRecipient(thread)) ?: authorPublicKey
quoteViewAuthorTextView.text = authorDisplayName
quoteViewAuthorTextView.setTextColor(getTextColor(isOutgoingMessage))

View File

@ -17,6 +17,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.isVisible
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.android.synthetic.main.view_visible_message.view.*
import network.loki.messenger.R
import org.session.libsession.messaging.contacts.Contact.ContactContext
@ -24,18 +25,27 @@ import org.session.libsession.messaging.open_groups.OpenGroupAPIV2
import org.session.libsession.utilities.ViewUtil
import org.session.libsignal.utilities.ThreadUtils
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.*
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.home.UserDetailsBottomSheet
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.util.*
import java.util.*
import javax.inject.Inject
import kotlin.math.abs
import kotlin.math.min
import kotlin.math.roundToInt
import kotlin.math.sqrt
@AndroidEntryPoint
class VisibleMessageView : LinearLayout {
@Inject lateinit var threadDb: ThreadDatabase
@Inject lateinit var contactDb: SessionContactDatabase
@Inject lateinit var lokiThreadDb: LokiThreadDatabase
@Inject lateinit var mmsSmsDb: MmsSmsDatabase
@Inject lateinit var smsDb: SmsDatabase
@Inject lateinit var mmsDb: MmsDatabase
private val screenWidth = Resources.getSystem().displayMetrics.widthPixels
private val swipeToReplyIcon = ContextCompat.getDrawable(context, R.drawable.ic_baseline_reply_24)!!.mutate()
private val swipeToReplyIconRect = Rect()
@ -82,10 +92,8 @@ class VisibleMessageView : LinearLayout {
val sender = message.individualRecipient
val senderSessionID = sender.address.serialize()
val threadID = message.threadId
val threadDB = DatabaseFactory.getThreadDatabase(context)
val thread = threadDB.getRecipientForThreadId(threadID) ?: return
val contactDB = DatabaseFactory.getSessionContactDatabase(context)
val contact = contactDB.getContactWithSessionID(senderSessionID)
val thread = threadDb.getRecipientForThreadId(threadID) ?: return
val contact = contactDb.getContactWithSessionID(senderSessionID)
val isGroupThread = thread.isGroupRecipient
val isStartOfMessageCluster = isStartOfMessageCluster(message, previous, isGroupThread)
val isEndOfMessageCluster = isEndOfMessageCluster(message, next, isGroupThread)
@ -98,7 +106,7 @@ class VisibleMessageView : LinearLayout {
profilePictureView.update(message.individualRecipient, threadID)
profilePictureView.setOnClickListener { showUserDetails(message.recipient.address.toString()) }
if (thread.isOpenGroupRecipient) {
val openGroup = DatabaseFactory.getLokiThreadDatabase(context).getOpenGroupChat(threadID) ?: return
val openGroup = lokiThreadDb.getOpenGroupChat(threadID) ?: return
val isModerator = OpenGroupAPIV2.isUserModerator(senderSessionID, openGroup.room, openGroup.server)
moderatorIconImageView.visibility = if (isModerator) View.VISIBLE else View.INVISIBLE
} else {
@ -143,7 +151,7 @@ class VisibleMessageView : LinearLayout {
messageStatusImageView.setImageDrawable(drawable)
}
if (message.isOutgoing) {
val lastMessageID = DatabaseFactory.getMmsSmsDatabase(context).getLastMessageID(message.threadId)
val lastMessageID = mmsSmsDb.getLastMessageID(message.threadId)
messageStatusImageView.isVisible = !message.isSent || message.id == lastMessageID
} else {
messageStatusImageView.isVisible = false
@ -225,7 +233,7 @@ class VisibleMessageView : LinearLayout {
val expirationManager = ApplicationContext.getInstance(context).expiringMessageManager
val id = message.getId()
val mms = message.isMms
if (mms) DatabaseFactory.getMmsDatabase(context).markExpireStarted(id) else DatabaseFactory.getSmsDatabase(context).markExpireStarted(id)
if (mms) mmsDb.markExpireStarted(id) else smsDb.markExpireStarted(id)
expirationManager.scheduleDeletion(id, mms, message.expiresIn)
}
} else {

View File

@ -3,25 +3,29 @@ package org.thoughtcrime.securesms.conversation.v2.messages
import android.content.Context
import android.graphics.Canvas
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.widget.LinearLayout
import android.widget.RelativeLayout
import androidx.core.view.isVisible
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.android.synthetic.main.view_voice_message.view.*
import network.loki.messenger.R
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
import org.thoughtcrime.securesms.audio.AudioSlidePlayer
import org.thoughtcrime.securesms.components.CornerMask
import org.thoughtcrime.securesms.conversation.v2.utilities.MessageBubbleUtilities
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.AttachmentDatabase
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import kotlin.math.roundToInt
import kotlin.math.roundToLong
@AndroidEntryPoint
class VoiceMessageView : LinearLayout, AudioSlidePlayer.Listener {
@Inject lateinit var attachmentDb: AttachmentDatabase
private val cornerMask by lazy { CornerMask(this) }
private var isPlaying = false
set(value) {
@ -67,7 +71,7 @@ class VoiceMessageView : LinearLayout, AudioSlidePlayer.Listener {
this.player = player
(audio.asAttachment() as? DatabaseAttachment)?.let { attachment ->
DatabaseFactory.getAttachmentDatabase(context).getAttachmentAudioExtras(attachment.attachmentId)?.let { audioExtras ->
attachmentDb.getAttachmentAudioExtras(attachment.attachmentId)?.let { audioExtras ->
if (audioExtras.durationMs > 0) {
duration = audioExtras.durationMs
voiceMessageViewDurationTextView.visibility = View.VISIBLE

View File

@ -1,21 +1,30 @@
package org.thoughtcrime.securesms.conversation.v2.search
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import android.content.Context
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import org.session.libsession.utilities.Debouncer
import org.session.libsession.utilities.Util.runOnMain
import org.session.libsession.utilities.concurrent.SignalExecutors
import org.thoughtcrime.securesms.contacts.ContactAccessor
import org.thoughtcrime.securesms.database.CursorList
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.SearchDatabase
import org.thoughtcrime.securesms.database.ThreadDatabase
import org.thoughtcrime.securesms.search.SearchRepository
import org.thoughtcrime.securesms.search.model.MessageResult
import org.thoughtcrime.securesms.util.CloseableLiveData
import java.io.Closeable
import javax.inject.Inject
@HiltViewModel
class SearchViewModel @Inject constructor(
@ApplicationContext context: Context,
searchDb: SearchDatabase,
threadDb: ThreadDatabase
) : ViewModel() {
class SearchViewModel(application: Application) : AndroidViewModel(application) {
private val searchRepository: SearchRepository
private val result: CloseableLiveData<SearchResult>
private val debouncer: Debouncer
@ -99,13 +108,12 @@ class SearchViewModel(application: Application) : AndroidViewModel(application)
}
init {
val context = application.applicationContext
result = CloseableLiveData()
debouncer = Debouncer(500)
searchRepository = SearchRepository(context,
DatabaseFactory.getSearchDatabase(context),
DatabaseFactory.getThreadDatabase(context),
ContactAccessor.getInstance(),
SignalExecutors.SERIAL)
searchDb,
threadDb,
ContactAccessor.getInstance(),
SignalExecutors.SERIAL)
}
}

View File

@ -1,10 +1,10 @@
package org.thoughtcrime.securesms.conversation.v2.utilities
import android.content.Context
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.messaging.mentions.MentionsManager
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
object MentionManagerUtilities {
@ -13,12 +13,12 @@ object MentionManagerUtilities {
if (MentionsManager.userPublicKeyCache[threadID] != null) return
val result = mutableSetOf<String>()
val recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadID) ?: return
val recipient = DatabaseComponent.get(context).threadDatabase().getRecipientForThreadId(threadID) ?: return
if (recipient.address.isClosedGroup) {
val members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(recipient.address.toGroupString(), false).map { it.address.serialize() }
val members = DatabaseComponent.get(context).groupDatabase().getGroupMembers(recipient.address.toGroupString(), false).map { it.address.serialize() }
result.addAll(members)
} else {
val messageDatabase = DatabaseFactory.getMmsSmsDatabase(context)
val messageDatabase = DatabaseComponent.get(context).mmsSmsDatabase()
val reader = messageDatabase.readerFor(messageDatabase.getConversation(threadID, 0, 200))
var record: MessageRecord? = reader.next
while (record != null) {

View File

@ -11,8 +11,8 @@ import androidx.core.content.res.ResourcesCompat
import network.loki.messenger.R
import nl.komponents.kovenant.combine.Tuple2
import org.session.libsession.messaging.contacts.Contact
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.util.UiModeUtilities
import java.util.regex.Pattern
@ -26,7 +26,7 @@ object MentionUtilities {
@JvmStatic
fun highlightMentions(text: CharSequence, isOutgoingMessage: Boolean, threadID: Long, context: Context): SpannableString {
@Suppress("NAME_SHADOWING") var text = text
val threadDB = DatabaseFactory.getThreadDatabase(context)
val threadDB = DatabaseComponent.get(context).threadDatabase()
val isOpenGroup = threadDB.getRecipientForThreadId(threadID)?.isOpenGroupRecipient ?: false
val pattern = Pattern.compile("@[0-9a-fA-F]*")
var matcher = pattern.matcher(text)
@ -39,7 +39,7 @@ object MentionUtilities {
val userDisplayName: String? = if (publicKey.equals(userPublicKey, ignoreCase = true)) {
TextSecurePreferences.getProfileName(context)
} else {
val contact = DatabaseFactory.getSessionContactDatabase(context).getContactWithSessionID(publicKey)
val contact = DatabaseComponent.get(context).sessionContactDatabase().getContactWithSessionID(publicKey)
@Suppress("NAME_SHADOWING") val context = if (isOpenGroup) Contact.ContactContext.OPEN_GROUP else Contact.ContactContext.REGULAR
contact?.displayName(context)
}

View File

@ -52,6 +52,7 @@ import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream;
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream;
import org.thoughtcrime.securesms.crypto.ModernEncryptingPartOutputStream;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.mms.MediaStream;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.PartAuthority;
@ -198,7 +199,7 @@ public class AttachmentDatabase extends Database {
values.put(TRANSFER_STATE, AttachmentTransferProgress.TRANSFER_PROGRESS_FAILED);
database.update(TABLE_NAME, values, PART_ID_WHERE, attachmentId.toStrings());
notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(mmsId));
notifyConversationListeners(DatabaseComponent.get(context).mmsDatabase().getThreadIdForMessage(mmsId));
}
public @Nullable DatabaseAttachment getAttachment(@NonNull AttachmentId attachmentId)
@ -370,7 +371,7 @@ public class AttachmentDatabase extends Database {
//noinspection ResultOfMethodCallIgnored
dataInfo.file.delete();
} else {
notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(mmsId));
notifyConversationListeners(DatabaseComponent.get(context).mmsDatabase().getThreadIdForMessage(mmsId));
notifyConversationListListeners();
}
@ -499,7 +500,7 @@ public class AttachmentDatabase extends Database {
values.put(TRANSFER_STATE, AttachmentTransferProgress.TRANSFER_PROGRESS_DONE);
database.update(TABLE_NAME, values, PART_ID_WHERE, ((DatabaseAttachment)attachment).getAttachmentId().toStrings());
notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId));
notifyConversationListeners(DatabaseComponent.get(context).mmsDatabase().getThreadIdForMessage(messageId));
((DatabaseAttachment) attachment).setUploaded(true);
}
@ -509,7 +510,7 @@ public class AttachmentDatabase extends Database {
values.put(TRANSFER_STATE, transferState);
database.update(TABLE_NAME, values, PART_ID_WHERE, attachmentId.toStrings());
notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId));
notifyConversationListeners(DatabaseComponent.get(context).mmsDatabase().getThreadIdForMessage(messageId));
}
@SuppressWarnings("WeakerAccess")
@ -782,7 +783,7 @@ public class AttachmentDatabase extends Database {
try {
if (cursor != null && cursor.moveToFirst()) {
notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(cursor.getLong(cursor.getColumnIndexOrThrow(MMS_ID))));
notifyConversationListeners(DatabaseComponent.get(context).mmsDatabase().getThreadIdForMessage(cursor.getLong(cursor.getColumnIndexOrThrow(MMS_ID))));
}
} finally {
if (cursor != null) cursor.close();

View File

@ -1,3 +1,4 @@
/*
* Copyright (C) 2018 Open Whisper Systems
*
@ -18,296 +19,15 @@ package org.thoughtcrime.securesms.database;
import android.content.Context;
import androidx.annotation.NonNull;
import net.sqlcipher.database.SQLiteDatabase;
import org.thoughtcrime.securesms.attachments.DatabaseAttachmentProvider;
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
import org.thoughtcrime.securesms.crypto.DatabaseSecret;
import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
public class DatabaseFactory {
private static final Object lock = new Object();
private static DatabaseFactory instance;
private final SQLCipherOpenHelper databaseHelper;
private SmsDatabase sms;
private MmsDatabase mms;
private AttachmentDatabase attachments;
private MediaDatabase media;
private ThreadDatabase thread;
private MmsSmsDatabase mmsSmsDatabase;
private DraftDatabase draftDatabase;
private PushDatabase pushDatabase;
private GroupDatabase groupDatabase;
private RecipientDatabase recipientDatabase;
private GroupReceiptDatabase groupReceiptDatabase;
private SearchDatabase searchDatabase;
private JobDatabase jobDatabase;
private LokiAPIDatabase lokiAPIDatabase;
private LokiMessageDatabase lokiMessageDatabase;
private LokiThreadDatabase lokiThreadDatabase;
private LokiUserDatabase lokiUserDatabase;
private LokiBackupFilesDatabase lokiBackupFilesDatabase;
private SessionJobDatabase sessionJobDatabase;
private SessionContactDatabase sessionContactDatabase;
private Storage storage;
private DatabaseAttachmentProvider attachmentProvider;
public static DatabaseFactory getInstance(Context context) {
synchronized (lock) {
if (instance == null)
instance = new DatabaseFactory(context.getApplicationContext());
return instance;
}
}
public static MmsSmsDatabase getMmsSmsDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.mmsSmsDatabase == null) {
factory.mmsSmsDatabase = new MmsSmsDatabase(context, factory.databaseHelper);
}
return factory.mmsSmsDatabase;
}
}
public static ThreadDatabase getThreadDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.thread == null) {
factory.thread = new ThreadDatabase(context, factory.databaseHelper);
}
return factory.thread;
}
}
public static SmsDatabase getSmsDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.sms == null) {
factory.sms = new SmsDatabase(context, factory.databaseHelper);
}
return factory.sms;
}
}
public static MmsDatabase getMmsDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.mms == null) {
factory.mms = new MmsDatabase(context, factory.databaseHelper);
}
return factory.mms;
}
}
public static AttachmentDatabase getAttachmentDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.attachments == null) {
AttachmentSecret attachmentSecret = AttachmentSecretProvider.getInstance(context).getOrCreateAttachmentSecret();
factory.attachments = new AttachmentDatabase(context, factory.databaseHelper, attachmentSecret);
}
return factory.attachments;
}
}
public static MediaDatabase getMediaDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.media == null) {
factory.media = new MediaDatabase(context, factory.databaseHelper);
}
return factory.media;
}
}
public static DraftDatabase getDraftDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.draftDatabase == null) {
factory.draftDatabase = new DraftDatabase(context, factory.databaseHelper);
}
return factory.draftDatabase;
}
}
public static PushDatabase getPushDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.pushDatabase == null) {
factory.pushDatabase = new PushDatabase(context, factory.databaseHelper);
}
return factory.pushDatabase;
}
}
public static GroupDatabase getGroupDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.groupDatabase == null) {
factory.groupDatabase = new GroupDatabase(context, factory.databaseHelper);
}
return factory.groupDatabase;
}
}
public static RecipientDatabase getRecipientDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.recipientDatabase == null) {
factory.recipientDatabase = new RecipientDatabase(context, factory.databaseHelper);
}
return factory.recipientDatabase;
}
}
public static GroupReceiptDatabase getGroupReceiptDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.groupReceiptDatabase == null) {
factory.groupReceiptDatabase = new GroupReceiptDatabase(context, factory.databaseHelper);
}
return factory.groupReceiptDatabase;
}
}
public static SearchDatabase getSearchDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.searchDatabase == null) {
factory.searchDatabase = new SearchDatabase(context, factory.databaseHelper);
}
return factory.searchDatabase;
}
}
public static JobDatabase getJobDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.jobDatabase == null) {
factory.jobDatabase = new JobDatabase(context, factory.databaseHelper);
}
return factory.jobDatabase;
}
}
public static SQLiteDatabase getBackupDatabase(Context context) {
return getInstance(context).databaseHelper.getReadableDatabase();
}
// region Loki
public static LokiAPIDatabase getLokiAPIDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.lokiAPIDatabase == null) {
factory.lokiAPIDatabase = new LokiAPIDatabase(context, factory.databaseHelper);
}
return factory.lokiAPIDatabase;
}
}
public static LokiMessageDatabase getLokiMessageDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.lokiMessageDatabase == null) {
factory.lokiMessageDatabase = new LokiMessageDatabase(context, factory.databaseHelper);
}
return factory.lokiMessageDatabase;
}
}
public static LokiThreadDatabase getLokiThreadDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.lokiThreadDatabase == null) {
factory.lokiThreadDatabase = new LokiThreadDatabase(context, factory.databaseHelper);
}
return factory.lokiThreadDatabase;
}
}
public static LokiUserDatabase getLokiUserDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.lokiUserDatabase == null) {
factory.lokiUserDatabase = new LokiUserDatabase(context, factory.databaseHelper);
}
return factory.lokiUserDatabase;
}
}
public static LokiBackupFilesDatabase getLokiBackupFilesDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.lokiBackupFilesDatabase == null) {
factory.lokiBackupFilesDatabase = new LokiBackupFilesDatabase(context, factory.databaseHelper);
}
return factory.lokiBackupFilesDatabase;
}
}
public static SessionJobDatabase getSessionJobDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.sessionJobDatabase == null) {
factory.sessionJobDatabase = new SessionJobDatabase(context, factory.databaseHelper);
}
return factory.sessionJobDatabase;
}
}
public static SessionContactDatabase getSessionContactDatabase(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.sessionContactDatabase == null) {
factory.sessionContactDatabase = new SessionContactDatabase(context, factory.databaseHelper);
}
return factory.sessionContactDatabase;
}
}
// endregion
// region Refactor
public static Storage getStorage(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.storage == null) {
factory.storage = new Storage(context, factory.databaseHelper);
}
return factory.storage;
}
}
public static DatabaseAttachmentProvider getAttachmentProvider(Context context) {
DatabaseFactory factory = getInstance(context);
synchronized (lock) {
if (factory.attachmentProvider == null) {
factory.attachmentProvider = new DatabaseAttachmentProvider(context, factory.databaseHelper);
}
return factory.attachmentProvider;
}
}
// endregion
public static void upgradeRestored(Context context, SQLiteDatabase database){
getInstance(context).databaseHelper.onUpgrade(database, database.getVersion(), -1);
getInstance(context).databaseHelper.markCurrent(database);
SQLCipherOpenHelper databaseHelper = DatabaseComponent.get(context).openHelper();
databaseHelper.onUpgrade(database, database.getVersion(), -1);
databaseHelper.markCurrent(database);
}
private DatabaseFactory(@NonNull Context context) {
SQLiteDatabase.loadLibs(context);
DatabaseSecret databaseSecret = new DatabaseSecretProvider(context).getOrCreateDatabaseSecret();
this.databaseHelper = new SQLCipherOpenHelper(context, databaseSecret);
}
}

View File

@ -3,11 +3,12 @@ package org.thoughtcrime.securesms.database
import android.content.ContentValues
import android.content.Context
import android.database.Cursor
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.session.libsession.messaging.open_groups.OpenGroupV2
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsignal.utilities.JsonUtil
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {
@ -26,7 +27,7 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
fun getThreadID(hexEncodedPublicKey: String): Long {
val address = Address.fromSerialized(hexEncodedPublicKey)
val recipient = Recipient.from(context, address, false)
return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient)
return DatabaseComponent.get(context).threadDatabase().getOrCreateThreadIdFor(recipient)
}
fun getAllV2OpenGroups(): Map<Long, OpenGroupV2> {

View File

@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.database;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -10,8 +11,8 @@ import net.sqlcipher.database.SQLiteDatabase;
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment;
import org.session.libsession.utilities.Address;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import java.util.List;
@ -60,7 +61,7 @@ public class MediaDatabase extends Database {
AttachmentDatabase.CONTENT_TYPE + " NOT LIKE 'audio/%' AND " +
AttachmentDatabase.CONTENT_TYPE + " NOT LIKE 'text/x-signal-plain'");
MediaDatabase(Context context, SQLCipherOpenHelper databaseHelper) {
public MediaDatabase(Context context, SQLCipherOpenHelper databaseHelper) {
super(context, databaseHelper);
}
@ -101,7 +102,7 @@ public class MediaDatabase extends Database {
}
public static MediaRecord from(@NonNull Context context, @NonNull Cursor cursor) {
AttachmentDatabase attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context);
AttachmentDatabase attachmentDatabase = DatabaseComponent.get(context).attachmentDatabase();
List<DatabaseAttachment> attachments = attachmentDatabase.getAttachment(cursor);
String serializedAddress = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.ADDRESS));
boolean outgoing = MessagingDatabase.Types.isOutgoingMessageType(cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_BOX)));

View File

@ -66,6 +66,7 @@ import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord;
import org.thoughtcrime.securesms.database.model.Quote;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.SlideDeck;
@ -264,8 +265,8 @@ public class MmsDatabase extends MessagingDatabase {
columnName + " = " + columnName + " + 1 WHERE " + ID + " = ?",
new String[] {String.valueOf(id)});
DatabaseFactory.getGroupReceiptDatabase(context).update(ourAddress, id, status, timestamp);
DatabaseFactory.getThreadDatabase(context).update(threadId, false);
DatabaseComponent.get(context).groupReceiptDatabase().update(ourAddress, id, status, timestamp);
DatabaseComponent.get(context).threadDatabase().update(threadId, false);
notifyConversationListeners(threadId);
}
}
@ -312,10 +313,10 @@ public class MmsDatabase extends MessagingDatabase {
private long getThreadIdFor(IncomingMediaMessage retrieved) throws RecipientFormattingException, MmsException {
if (retrieved.getGroupId() != null) {
Recipient groupRecipients = Recipient.from(context, retrieved.getGroupId(), true);
return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(groupRecipients);
return DatabaseComponent.get(context).threadDatabase().getOrCreateThreadIdFor(groupRecipients);
} else {
Recipient sender = Recipient.from(context, retrieved.getFrom(), true);
return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(sender);
return DatabaseComponent.get(context).threadDatabase().getOrCreateThreadIdFor(sender);
}
}
@ -324,7 +325,7 @@ public class MmsDatabase extends MessagingDatabase {
? Util.toIsoString(notification.getFrom().getTextString())
: "";
Recipient recipient = Recipient.from(context, Address.fromExternal(context, fromString), false);
return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
return DatabaseComponent.get(context).threadDatabase().getOrCreateThreadIdFor(recipient);
}
private Cursor rawQuery(@NonNull String where, @Nullable String[] arguments) {
@ -353,7 +354,7 @@ public class MmsDatabase extends MessagingDatabase {
" WHERE " + ID + " = ?", new String[] {id + ""});
if (threadId.isPresent()) {
DatabaseFactory.getThreadDatabase(context).update(threadId.get(), false);
DatabaseComponent.get(context).threadDatabase().update(threadId.get(), false);
}
}
@ -399,11 +400,11 @@ public class MmsDatabase extends MessagingDatabase {
contentValues.put(BODY, "");
database.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {String.valueOf(messageId)});
AttachmentDatabase attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context);
AttachmentDatabase attachmentDatabase = DatabaseComponent.get(context).attachmentDatabase();
ThreadUtils.queue(() -> attachmentDatabase.deleteAttachmentsForMessage(messageId));
long threadId = getThreadIdForMessage(messageId);
if (!read) { DatabaseFactory.getThreadDatabase(context).decrementUnread(threadId, 1); }
if (!read) { DatabaseComponent.get(context).threadDatabase().decrementUnread(threadId, 1); }
updateMailboxBitmask(messageId, Types.BASE_TYPE_MASK, Types.BASE_DELETED_TYPE, Optional.of(threadId));
notifyConversationListeners(threadId);
}
@ -478,7 +479,7 @@ public class MmsDatabase extends MessagingDatabase {
public OutgoingMediaMessage getOutgoingMessage(long messageId)
throws MmsException, NoSuchMessageException
{
AttachmentDatabase attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context);
AttachmentDatabase attachmentDatabase = DatabaseComponent.get(context).attachmentDatabase();
Cursor cursor = null;
try {
@ -494,7 +495,7 @@ public class MmsDatabase extends MessagingDatabase {
long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(EXPIRES_IN));
String address = cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS));
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID));
int distributionType = DatabaseFactory.getThreadDatabase(context).getDistributionType(threadId);
int distributionType = DatabaseComponent.get(context).threadDatabase().getDistributionType(threadId);
String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.MISMATCHED_IDENTITIES));
String networkDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.NETWORK_FAILURE));
@ -687,8 +688,8 @@ public class MmsDatabase extends MessagingDatabase {
long messageId = insertMediaMessage(retrieved.getBody(), retrieved.getAttachments(), quoteAttachments, retrieved.getSharedContacts(), retrieved.getLinkPreviews(), contentValues, null);
if (!Types.isExpirationTimerUpdate(mailbox)) {
DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1);
DatabaseFactory.getThreadDatabase(context).update(threadId, true);
DatabaseComponent.get(context).threadDatabase().incrementUnread(threadId, 1);
DatabaseComponent.get(context).threadDatabase().update(threadId, true);
}
notifyConversationListeners(threadId);
@ -715,9 +716,9 @@ public class MmsDatabase extends MessagingDatabase {
throw new MmsException(e);
}
Recipient group = Recipient.from(context, Address.fromSerialized(groupId), false);
threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(group);
threadId = DatabaseComponent.get(context).threadDatabase().getOrCreateThreadIdFor(group);
} else {
threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(retrieved.getRecipient());
threadId = DatabaseComponent.get(context).threadDatabase().getOrCreateThreadIdFor(retrieved.getRecipient());
}
}
long messageId = insertMessageOutbox(retrieved, threadId, false, null, serverTimestamp);
@ -823,8 +824,8 @@ public class MmsDatabase extends MessagingDatabase {
long messageId = insertMediaMessage(message.getBody(), message.getAttachments(), quoteAttachments, message.getSharedContacts(), message.getLinkPreviews(), contentValues, insertListener);
if (message.getRecipient().getAddress().isGroup()) {
List<Recipient> members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(message.getRecipient().getAddress().toGroupString(), false);
GroupReceiptDatabase receiptDatabase = DatabaseFactory.getGroupReceiptDatabase(context);
List<Recipient> members = DatabaseComponent.get(context).groupDatabase().getGroupMembers(message.getRecipient().getAddress().toGroupString(), false);
GroupReceiptDatabase receiptDatabase = DatabaseComponent.get(context).groupReceiptDatabase();
receiptDatabase.insert(Stream.of(members).map(Recipient::getAddress).toList(),
messageId, GroupReceiptDatabase.STATUS_UNDELIVERED, message.getSentTimeMillis());
@ -833,8 +834,8 @@ public class MmsDatabase extends MessagingDatabase {
for (Address address : earlyReadReceipts.keySet()) receiptDatabase.update(address, messageId, GroupReceiptDatabase.STATUS_READ, -1);
}
DatabaseFactory.getThreadDatabase(context).setLastSeen(threadId);
DatabaseFactory.getThreadDatabase(context).setHasSent(threadId, true);
DatabaseComponent.get(context).threadDatabase().setLastSeen(threadId);
DatabaseComponent.get(context).threadDatabase().setHasSent(threadId, true);
return messageId;
}
@ -849,7 +850,7 @@ public class MmsDatabase extends MessagingDatabase {
throws MmsException
{
SQLiteDatabase db = databaseHelper.getWritableDatabase();
AttachmentDatabase partsDatabase = DatabaseFactory.getAttachmentDatabase(context);
AttachmentDatabase partsDatabase = DatabaseComponent.get(context).attachmentDatabase();
List<Attachment> allAttachments = new LinkedList<>();
List<Attachment> contactAttachments = Stream.of(sharedContacts).map(Contact::getAvatarAttachment).filter(a -> a != null).toList();
@ -904,7 +905,7 @@ public class MmsDatabase extends MessagingDatabase {
}
notifyConversationListeners(contentValues.getAsLong(THREAD_ID));
DatabaseFactory.getThreadDatabase(context).update(contentValues.getAsLong(THREAD_ID), true);
DatabaseComponent.get(context).threadDatabase().update(contentValues.getAsLong(THREAD_ID), true);
}
}
@ -926,10 +927,10 @@ public class MmsDatabase extends MessagingDatabase {
@Override
public boolean deleteMessage(long messageId) {
long threadId = getThreadIdForMessage(messageId);
AttachmentDatabase attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context);
AttachmentDatabase attachmentDatabase = DatabaseComponent.get(context).attachmentDatabase();
ThreadUtils.queue(() -> attachmentDatabase.deleteAttachmentsForMessage(messageId));
GroupReceiptDatabase groupReceiptDatabase = DatabaseFactory.getGroupReceiptDatabase(context);
GroupReceiptDatabase groupReceiptDatabase = DatabaseComponent.get(context).groupReceiptDatabase();
groupReceiptDatabase.deleteRowsForMessage(messageId);
MessageRecord toDelete;
@ -940,7 +941,7 @@ public class MmsDatabase extends MessagingDatabase {
deleteQuotedFromMessages(toDelete);
SQLiteDatabase database = databaseHelper.getWritableDatabase();
database.delete(TABLE_NAME, ID_WHERE, new String[] {messageId+""});
boolean threadDeleted = DatabaseFactory.getThreadDatabase(context).update(threadId, false);
boolean threadDeleted = DatabaseComponent.get(context).threadDatabase().update(threadId, false);
notifyConversationListeners(threadId);
notifyStickerListeners();
notifyStickerPackListeners();
@ -1088,8 +1089,8 @@ public class MmsDatabase extends MessagingDatabase {
public void deleteAllThreads() {
DatabaseFactory.getAttachmentDatabase(context).deleteAllAttachments();
DatabaseFactory.getGroupReceiptDatabase(context).deleteAllRows();
DatabaseComponent.get(context).attachmentDatabase().deleteAllAttachments();
DatabaseComponent.get(context).groupReceiptDatabase().deleteAllRows();
SQLiteDatabase database = databaseHelper.getWritableDatabase();
database.delete(TABLE_NAME, null, null);
@ -1258,7 +1259,7 @@ public class MmsDatabase extends MessagingDatabase {
Recipient recipient = getRecipientFor(address);
List<IdentityKeyMismatch> mismatches = getMismatchedIdentities(mismatchDocument);
List<NetworkFailure> networkFailures = getFailures(networkDocument);
List<DatabaseAttachment> attachments = DatabaseFactory.getAttachmentDatabase(context).getAttachment(cursor);
List<DatabaseAttachment> attachments = DatabaseComponent.get(context).attachmentDatabase().getAttachment(cursor);
List<Contact> contacts = getSharedContacts(cursor, attachments);
Set<Attachment> contactAttachments = Stream.of(contacts).map(Contact::getAvatarAttachment).filter(a -> a != null).collect(Collectors.toSet());
List<LinkPreview> previews = getLinkPreviews(cursor, attachments);
@ -1321,7 +1322,7 @@ public class MmsDatabase extends MessagingDatabase {
String quoteAuthor = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.QUOTE_AUTHOR));
String quoteText = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.QUOTE_BODY));
boolean quoteMissing = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.QUOTE_MISSING)) == 1;
List<DatabaseAttachment> attachments = DatabaseFactory.getAttachmentDatabase(context).getAttachment(cursor);
List<DatabaseAttachment> attachments = DatabaseComponent.get(context).attachmentDatabase().getAttachment(cursor);
List<? extends Attachment> quoteAttachments = Stream.of(attachments).filter(Attachment::isQuote).toList();
SlideDeck quoteDeck = new SlideDeck(context, quoteAttachments);

View File

@ -30,6 +30,7 @@ import org.session.libsession.utilities.Util;
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import java.util.HashSet;
import java.util.Set;
@ -161,20 +162,20 @@ public class MmsSmsDatabase extends Database {
}
public int getConversationCount(long threadId) {
int count = DatabaseFactory.getSmsDatabase(context).getMessageCountForThread(threadId);
count += DatabaseFactory.getMmsDatabase(context).getMessageCountForThread(threadId);
int count = DatabaseComponent.get(context).smsDatabase().getMessageCountForThread(threadId);
count += DatabaseComponent.get(context).mmsDatabase().getMessageCountForThread(threadId);
return count;
}
public void incrementDeliveryReceiptCount(SyncMessageId syncMessageId, long timestamp) {
DatabaseFactory.getSmsDatabase(context).incrementReceiptCount(syncMessageId, true, false);
DatabaseFactory.getMmsDatabase(context).incrementReceiptCount(syncMessageId, timestamp, true, false);
DatabaseComponent.get(context).smsDatabase().incrementReceiptCount(syncMessageId, true, false);
DatabaseComponent.get(context).mmsDatabase().incrementReceiptCount(syncMessageId, timestamp, true, false);
}
public void incrementReadReceiptCount(SyncMessageId syncMessageId, long timestamp) {
DatabaseFactory.getSmsDatabase(context).incrementReceiptCount(syncMessageId, false, true);
DatabaseFactory.getMmsDatabase(context).incrementReceiptCount(syncMessageId, timestamp, false, true);
DatabaseComponent.get(context).smsDatabase().incrementReceiptCount(syncMessageId, false, true);
DatabaseComponent.get(context).mmsDatabase().incrementReceiptCount(syncMessageId, timestamp, false, true);
}
public int getQuotedMessagePosition(long threadId, long quoteId, @NonNull Address address) {
@ -417,7 +418,7 @@ public class MmsSmsDatabase extends Database {
private SmsDatabase.Reader getSmsReader() {
if (smsReader == null) {
smsReader = DatabaseFactory.getSmsDatabase(context).readerFor(cursor);
smsReader = DatabaseComponent.get(context).smsDatabase().readerFor(cursor);
}
return smsReader;
@ -425,7 +426,7 @@ public class MmsSmsDatabase extends Database {
private MmsDatabase.Reader getMmsReader() {
if (mmsReader == null) {
mmsReader = DatabaseFactory.getMmsDatabase(context).readerFor(cursor);
mmsReader = DatabaseComponent.get(context).mmsDatabase().readerFor(cursor);
}
return mmsReader;

View File

@ -43,6 +43,7 @@ import org.session.libsignal.utilities.guava.Optional;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import java.io.IOException;
import java.security.SecureRandom;
@ -120,7 +121,7 @@ public class SmsDatabase extends MessagingDatabase {
long threadId = getThreadIdForMessage(id);
DatabaseFactory.getThreadDatabase(context).update(threadId, false);
DatabaseComponent.get(context).threadDatabase().update(threadId, false);
notifyConversationListeners(threadId);
}
@ -191,7 +192,7 @@ public class SmsDatabase extends MessagingDatabase {
contentValues.put(BODY, "");
database.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {String.valueOf(messageId)});
long threadId = getThreadIdForMessage(messageId);
if (!read) { DatabaseFactory.getThreadDatabase(context).decrementUnread(threadId, 1); }
if (!read) { DatabaseComponent.get(context).threadDatabase().decrementUnread(threadId, 1); }
updateTypeBitmask(messageId, Types.BASE_TYPE_MASK, Types.BASE_DELETED_TYPE);
}
@ -210,7 +211,7 @@ public class SmsDatabase extends MessagingDatabase {
long threadId = getThreadIdForMessage(id);
DatabaseFactory.getThreadDatabase(context).update(threadId, false);
DatabaseComponent.get(context).threadDatabase().update(threadId, false);
notifyConversationListeners(threadId);
}
@ -273,7 +274,7 @@ public class SmsDatabase extends MessagingDatabase {
ID + " = ?",
new String[] {String.valueOf(cursor.getLong(cursor.getColumnIndexOrThrow(ID)))});
DatabaseFactory.getThreadDatabase(context).update(threadId, false);
DatabaseComponent.get(context).threadDatabase().update(threadId, false);
notifyConversationListeners(threadId);
foundMessage = true;
}
@ -353,7 +354,7 @@ public class SmsDatabase extends MessagingDatabase {
long threadId = getThreadIdForMessage(messageId);
DatabaseFactory.getThreadDatabase(context).update(threadId, true);
DatabaseComponent.get(context).threadDatabase().update(threadId, true);
notifyConversationListeners(threadId);
notifyConversationListListeners();
@ -387,8 +388,8 @@ public class SmsDatabase extends MessagingDatabase {
long threadId;
if (groupRecipient == null) threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
else threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(groupRecipient);
if (groupRecipient == null) threadId = DatabaseComponent.get(context).threadDatabase().getOrCreateThreadIdFor(recipient);
else threadId = DatabaseComponent.get(context).threadDatabase().getOrCreateThreadIdFor(groupRecipient);
ContentValues values = new ContentValues(6);
values.put(ADDRESS, message.getSender().serialize());
@ -421,13 +422,13 @@ public class SmsDatabase extends MessagingDatabase {
long messageId = db.insert(TABLE_NAME, null, values);
if (unread) {
DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1);
DatabaseComponent.get(context).threadDatabase().incrementUnread(threadId, 1);
}
DatabaseFactory.getThreadDatabase(context).update(threadId, true);
DatabaseComponent.get(context).threadDatabase().update(threadId, true);
if (message.getSubscriptionId() != -1) {
DatabaseFactory.getRecipientDatabase(context).setDefaultSubscriptionId(recipient, message.getSubscriptionId());
DatabaseComponent.get(context).recipientDatabase().setDefaultSubscriptionId(recipient, message.getSubscriptionId());
}
notifyConversationListeners(threadId);
@ -446,7 +447,7 @@ public class SmsDatabase extends MessagingDatabase {
public Optional<InsertResult> insertMessageOutbox(long threadId, OutgoingTextMessage message, long serverTimestamp) {
if (threadId == -1) {
threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(message.getRecipient());
threadId = DatabaseComponent.get(context).threadDatabase().getOrCreateThreadIdFor(message.getRecipient());
}
long messageId = insertMessageOutbox(threadId, message, false, serverTimestamp, null);
if (messageId == -1) {
@ -493,10 +494,10 @@ public class SmsDatabase extends MessagingDatabase {
insertListener.onComplete();
}
DatabaseFactory.getThreadDatabase(context).update(threadId, true);
DatabaseFactory.getThreadDatabase(context).setLastSeen(threadId);
DatabaseComponent.get(context).threadDatabase().update(threadId, true);
DatabaseComponent.get(context).threadDatabase().setLastSeen(threadId);
DatabaseFactory.getThreadDatabase(context).setHasSent(threadId, true);
DatabaseComponent.get(context).threadDatabase().setHasSent(threadId, true);
notifyConversationListeners(threadId);
@ -536,12 +537,12 @@ public class SmsDatabase extends MessagingDatabase {
long threadId = getThreadIdForMessage(messageId);
try {
SmsMessageRecord toDelete = getMessage(messageId);
DatabaseFactory.getMmsDatabase(context).deleteQuotedFromMessages(toDelete);
DatabaseComponent.get(context).mmsDatabase().deleteQuotedFromMessages(toDelete);
} catch (NoSuchMessageException e) {
Log.e(TAG, "Couldn't find message record for messageId "+messageId, e);
}
db.delete(TABLE_NAME, ID_WHERE, new String[] {messageId+""});
boolean threadDeleted = DatabaseFactory.getThreadDatabase(context).update(threadId, false);
boolean threadDeleted = DatabaseComponent.get(context).threadDatabase().update(threadId, false);
notifyConversationListeners(threadId);
return threadDeleted;
}

View File

@ -28,6 +28,7 @@ import org.session.libsignal.utilities.KeyHelper
import org.session.libsignal.utilities.guava.Optional
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.groups.OpenGroupManager
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
import org.thoughtcrime.securesms.mms.PartAuthority
@ -40,7 +41,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
override fun getUserX25519KeyPair(): ECKeyPair {
return DatabaseFactory.getLokiAPIDatabase(context).getUserX25519KeyPair()
return DatabaseComponent.get(context).lokiAPIDatabase().getUserX25519KeyPair()
}
override fun getUserDisplayName(): String? {
@ -74,13 +75,13 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
override fun persistAttachments(messageID: Long, attachments: List<Attachment>): List<Long> {
val database = DatabaseFactory.getAttachmentDatabase(context)
val database = DatabaseComponent.get(context).attachmentDatabase()
val databaseAttachments = attachments.mapNotNull { it.toSignalAttachment() }
return database.insertAttachments(messageID, databaseAttachments)
}
override fun getAttachmentsForMessage(messageID: Long): List<DatabaseAttachment> {
val database = DatabaseFactory.getAttachmentDatabase(context)
val database = DatabaseComponent.get(context).attachmentDatabase()
return database.getAttachmentsForMessage(messageID)
}
@ -110,7 +111,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
if (message.isMediaMessage() || attachments.isNotEmpty()) {
val quote: Optional<QuoteModel> = if (quotes != null) Optional.of(quotes) else Optional.absent()
val linkPreviews: Optional<List<LinkPreview>> = if (linkPreview.isEmpty()) Optional.absent() else Optional.of(linkPreview.mapNotNull { it!! })
val mmsDatabase = DatabaseFactory.getMmsDatabase(context)
val mmsDatabase = DatabaseComponent.get(context).mmsDatabase()
val insertResult = if (message.sender == getUserPublicKey()) {
val mediaMessage = OutgoingMediaMessage.from(message, targetRecipient, pointers, quote.orNull(), linkPreviews.orNull()?.firstOrNull())
mmsDatabase.insertSecureDecryptedMessageOutbox(mediaMessage, message.threadID ?: -1, message.sentTimestamp!!)
@ -126,7 +127,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
messageID = insertResult.get().messageId
}
} else {
val smsDatabase = DatabaseFactory.getSmsDatabase(context)
val smsDatabase = DatabaseComponent.get(context).smsDatabase()
val isOpenGroupInvitation = (message.openGroupInvitation != null)
val insertResult = if (message.sender == getUserPublicKey()) {
@ -150,62 +151,62 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
message.serverHash?.let { serverHash ->
messageID?.let { id ->
DatabaseFactory.getLokiMessageDatabase(context).setMessageServerHash(id, serverHash)
DatabaseComponent.get(context).lokiMessageDatabase().setMessageServerHash(id, serverHash)
}
}
return messageID
}
override fun persistJob(job: Job) {
DatabaseFactory.getSessionJobDatabase(context).persistJob(job)
DatabaseComponent.get(context).sessionJobDatabase().persistJob(job)
}
override fun markJobAsSucceeded(jobId: String) {
DatabaseFactory.getSessionJobDatabase(context).markJobAsSucceeded(jobId)
DatabaseComponent.get(context).sessionJobDatabase().markJobAsSucceeded(jobId)
}
override fun markJobAsFailedPermanently(jobId: String) {
DatabaseFactory.getSessionJobDatabase(context).markJobAsFailedPermanently(jobId)
DatabaseComponent.get(context).sessionJobDatabase().markJobAsFailedPermanently(jobId)
}
override fun getAllPendingJobs(type: String): Map<String, Job?> {
return DatabaseFactory.getSessionJobDatabase(context).getAllPendingJobs(type)
return DatabaseComponent.get(context).sessionJobDatabase().getAllPendingJobs(type)
}
override fun getAttachmentUploadJob(attachmentID: Long): AttachmentUploadJob? {
return DatabaseFactory.getSessionJobDatabase(context).getAttachmentUploadJob(attachmentID)
return DatabaseComponent.get(context).sessionJobDatabase().getAttachmentUploadJob(attachmentID)
}
override fun getMessageSendJob(messageSendJobID: String): MessageSendJob? {
return DatabaseFactory.getSessionJobDatabase(context).getMessageSendJob(messageSendJobID)
return DatabaseComponent.get(context).sessionJobDatabase().getMessageSendJob(messageSendJobID)
}
override fun getMessageReceiveJob(messageReceiveJobID: String): MessageReceiveJob? {
return DatabaseFactory.getSessionJobDatabase(context).getMessageReceiveJob(messageReceiveJobID)
return DatabaseComponent.get(context).sessionJobDatabase().getMessageReceiveJob(messageReceiveJobID)
}
override fun resumeMessageSendJobIfNeeded(messageSendJobID: String) {
val job = DatabaseFactory.getSessionJobDatabase(context).getMessageSendJob(messageSendJobID) ?: return
val job = DatabaseComponent.get(context).sessionJobDatabase().getMessageSendJob(messageSendJobID) ?: return
JobQueue.shared.resumePendingSendMessage(job)
}
override fun isJobCanceled(job: Job): Boolean {
return DatabaseFactory.getSessionJobDatabase(context).isJobCanceled(job)
return DatabaseComponent.get(context).sessionJobDatabase().isJobCanceled(job)
}
override fun getAuthToken(room: String, server: String): String? {
val id = "$server.$room"
return DatabaseFactory.getLokiAPIDatabase(context).getAuthToken(id)
return DatabaseComponent.get(context).lokiAPIDatabase().getAuthToken(id)
}
override fun setAuthToken(room: String, server: String, newValue: String) {
val id = "$server.$room"
DatabaseFactory.getLokiAPIDatabase(context).setAuthToken(id, newValue)
DatabaseComponent.get(context).lokiAPIDatabase().setAuthToken(id, newValue)
}
override fun removeAuthToken(room: String, server: String) {
val id = "$server.$room"
DatabaseFactory.getLokiAPIDatabase(context).setAuthToken(id, null)
DatabaseComponent.get(context).lokiAPIDatabase().setAuthToken(id, null)
}
override fun getV2OpenGroup(threadId: Long): OpenGroupV2? {
@ -218,44 +219,44 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
override fun getOpenGroupPublicKey(server: String): String? {
return DatabaseFactory.getLokiAPIDatabase(context).getOpenGroupPublicKey(server)
return DatabaseComponent.get(context).lokiAPIDatabase().getOpenGroupPublicKey(server)
}
override fun setOpenGroupPublicKey(server: String, newValue: String) {
DatabaseFactory.getLokiAPIDatabase(context).setOpenGroupPublicKey(server, newValue)
DatabaseComponent.get(context).lokiAPIDatabase().setOpenGroupPublicKey(server, newValue)
}
override fun getLastMessageServerID(room: String, server: String): Long? {
return DatabaseFactory.getLokiAPIDatabase(context).getLastMessageServerID(room, server)
return DatabaseComponent.get(context).lokiAPIDatabase().getLastMessageServerID(room, server)
}
override fun setLastMessageServerID(room: String, server: String, newValue: Long) {
DatabaseFactory.getLokiAPIDatabase(context).setLastMessageServerID(room, server, newValue)
DatabaseComponent.get(context).lokiAPIDatabase().setLastMessageServerID(room, server, newValue)
}
override fun removeLastMessageServerID(room: String, server: String) {
DatabaseFactory.getLokiAPIDatabase(context).removeLastMessageServerID(room, server)
DatabaseComponent.get(context).lokiAPIDatabase().removeLastMessageServerID(room, server)
}
override fun getLastDeletionServerID(room: String, server: String): Long? {
return DatabaseFactory.getLokiAPIDatabase(context).getLastDeletionServerID(room, server)
return DatabaseComponent.get(context).lokiAPIDatabase().getLastDeletionServerID(room, server)
}
override fun setLastDeletionServerID(room: String, server: String, newValue: Long) {
DatabaseFactory.getLokiAPIDatabase(context).setLastDeletionServerID(room, server, newValue)
DatabaseComponent.get(context).lokiAPIDatabase().setLastDeletionServerID(room, server, newValue)
}
override fun removeLastDeletionServerID(room: String, server: String) {
DatabaseFactory.getLokiAPIDatabase(context).removeLastDeletionServerID(room, server)
DatabaseComponent.get(context).lokiAPIDatabase().removeLastDeletionServerID(room, server)
}
override fun setUserCount(room: String, server: String, newValue: Int) {
DatabaseFactory.getLokiAPIDatabase(context).setUserCount(room, server, newValue)
DatabaseComponent.get(context).lokiAPIDatabase().setUserCount(room, server, newValue)
}
override fun setOpenGroupServerMessageID(messageID: Long, serverID: Long, threadID: Long, isSms: Boolean) {
DatabaseFactory.getLokiMessageDatabase(context).setServerID(messageID, serverID, isSms)
DatabaseFactory.getLokiMessageDatabase(context).setOriginalThreadID(messageID, serverID, threadID)
DatabaseComponent.get(context).lokiMessageDatabase().setServerID(messageID, serverID, isSms)
DatabaseComponent.get(context).lokiMessageDatabase().setOriginalThreadID(messageID, serverID, threadID)
}
override fun isDuplicateMessage(timestamp: Long): Boolean {
@ -263,11 +264,11 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
override fun updateTitle(groupID: String, newValue: String) {
DatabaseFactory.getGroupDatabase(context).updateTitle(groupID, newValue)
DatabaseComponent.get(context).groupDatabase().updateTitle(groupID, newValue)
}
override fun updateProfilePicture(groupID: String, newValue: ByteArray) {
DatabaseFactory.getGroupDatabase(context).updateProfilePicture(groupID, newValue)
DatabaseComponent.get(context).groupDatabase().updateProfilePicture(groupID, newValue)
}
override fun getReceivedMessageTimestamps(): Set<Long> {
@ -283,7 +284,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
override fun getMessageIdInDatabase(timestamp: Long, author: String): Long? {
val database = DatabaseFactory.getMmsSmsDatabase(context)
val database = DatabaseComponent.get(context).mmsSmsDatabase()
val address = Address.fromSerialized(author)
return database.getMessageFor(timestamp, address)?.getId()
}
@ -295,59 +296,59 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
threadId: Long
) {
if (isMms) {
val mmsDb = DatabaseFactory.getMmsDatabase(context)
val mmsDb = DatabaseComponent.get(context).mmsDatabase()
mmsDb.updateSentTimestamp(messageID, openGroupSentTimestamp, threadId)
} else {
val smsDb = DatabaseFactory.getSmsDatabase(context)
val smsDb = DatabaseComponent.get(context).smsDatabase()
smsDb.updateSentTimestamp(messageID, openGroupSentTimestamp, threadId)
}
}
override fun markAsSent(timestamp: Long, author: String) {
val database = DatabaseFactory.getMmsSmsDatabase(context)
val database = DatabaseComponent.get(context).mmsSmsDatabase()
val messageRecord = database.getMessageFor(timestamp, author) ?: return
if (messageRecord.isMms) {
val mmsDatabase = DatabaseFactory.getMmsDatabase(context)
val mmsDatabase = DatabaseComponent.get(context).mmsDatabase()
mmsDatabase.markAsSent(messageRecord.getId(), true)
} else {
val smsDatabase = DatabaseFactory.getSmsDatabase(context)
val smsDatabase = DatabaseComponent.get(context).smsDatabase()
smsDatabase.markAsSent(messageRecord.getId(), true)
}
}
override fun markAsSending(timestamp: Long, author: String) {
val database = DatabaseFactory.getMmsSmsDatabase(context)
val database = DatabaseComponent.get(context).mmsSmsDatabase()
val messageRecord = database.getMessageFor(timestamp, author) ?: return
if (messageRecord.isMms) {
val mmsDatabase = DatabaseFactory.getMmsDatabase(context)
val mmsDatabase = DatabaseComponent.get(context).mmsDatabase()
mmsDatabase.markAsSending(messageRecord.getId())
} else {
val smsDatabase = DatabaseFactory.getSmsDatabase(context)
val smsDatabase = DatabaseComponent.get(context).smsDatabase()
smsDatabase.markAsSending(messageRecord.getId())
messageRecord.isPending
}
}
override fun markUnidentified(timestamp: Long, author: String) {
val database = DatabaseFactory.getMmsSmsDatabase(context)
val database = DatabaseComponent.get(context).mmsSmsDatabase()
val messageRecord = database.getMessageFor(timestamp, author) ?: return
if (messageRecord.isMms) {
val mmsDatabase = DatabaseFactory.getMmsDatabase(context)
val mmsDatabase = DatabaseComponent.get(context).mmsDatabase()
mmsDatabase.markUnidentified(messageRecord.getId(), true)
} else {
val smsDatabase = DatabaseFactory.getSmsDatabase(context)
val smsDatabase = DatabaseComponent.get(context).smsDatabase()
smsDatabase.markUnidentified(messageRecord.getId(), true)
}
}
override fun setErrorMessage(timestamp: Long, author: String, error: Exception) {
val database = DatabaseFactory.getMmsSmsDatabase(context)
val database = DatabaseComponent.get(context).mmsSmsDatabase()
val messageRecord = database.getMessageFor(timestamp, author) ?: return
if (messageRecord.isMms) {
val mmsDatabase = DatabaseFactory.getMmsDatabase(context)
val mmsDatabase = DatabaseComponent.get(context).mmsDatabase()
mmsDatabase.markAsSentFailed(messageRecord.getId())
} else {
val smsDatabase = DatabaseFactory.getSmsDatabase(context)
val smsDatabase = DatabaseComponent.get(context).smsDatabase()
smsDatabase.markAsSentFailed(messageRecord.getId())
}
if (error.localizedMessage != null) {
@ -357,47 +358,47 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
} else {
message = error.localizedMessage!!
}
DatabaseFactory.getLokiMessageDatabase(context).setErrorMessage(messageRecord.getId(), message)
DatabaseComponent.get(context).lokiMessageDatabase().setErrorMessage(messageRecord.getId(), message)
} else {
DatabaseFactory.getLokiMessageDatabase(context).setErrorMessage(messageRecord.getId(), error.javaClass.simpleName)
DatabaseComponent.get(context).lokiMessageDatabase().setErrorMessage(messageRecord.getId(), error.javaClass.simpleName)
}
}
override fun setMessageServerHash(messageID: Long, serverHash: String) {
DatabaseFactory.getLokiMessageDatabase(context).setMessageServerHash(messageID, serverHash)
DatabaseComponent.get(context).lokiMessageDatabase().setMessageServerHash(messageID, serverHash)
}
override fun getGroup(groupID: String): GroupRecord? {
val group = DatabaseFactory.getGroupDatabase(context).getGroup(groupID)
val group = DatabaseComponent.get(context).groupDatabase().getGroup(groupID)
return if (group.isPresent) { group.get() } else null
}
override fun createGroup(groupId: String, title: String?, members: List<Address>, avatar: SignalServiceAttachmentPointer?, relay: String?, admins: List<Address>, formationTimestamp: Long) {
DatabaseFactory.getGroupDatabase(context).create(groupId, title, members, avatar, relay, admins, formationTimestamp)
DatabaseComponent.get(context).groupDatabase().create(groupId, title, members, avatar, relay, admins, formationTimestamp)
}
override fun isGroupActive(groupPublicKey: String): Boolean {
return DatabaseFactory.getGroupDatabase(context).getGroup(GroupUtil.doubleEncodeGroupID(groupPublicKey)).orNull()?.isActive == true
return DatabaseComponent.get(context).groupDatabase().getGroup(GroupUtil.doubleEncodeGroupID(groupPublicKey)).orNull()?.isActive == true
}
override fun setActive(groupID: String, value: Boolean) {
DatabaseFactory.getGroupDatabase(context).setActive(groupID, value)
DatabaseComponent.get(context).groupDatabase().setActive(groupID, value)
}
override fun getZombieMembers(groupID: String): Set<String> {
return DatabaseFactory.getGroupDatabase(context).getGroupZombieMembers(groupID).map { it.address.serialize() }.toHashSet()
return DatabaseComponent.get(context).groupDatabase().getGroupZombieMembers(groupID).map { it.address.serialize() }.toHashSet()
}
override fun removeMember(groupID: String, member: Address) {
DatabaseFactory.getGroupDatabase(context).removeMember(groupID, member)
DatabaseComponent.get(context).groupDatabase().removeMember(groupID, member)
}
override fun updateMembers(groupID: String, members: List<Address>) {
DatabaseFactory.getGroupDatabase(context).updateMembers(groupID, members)
DatabaseComponent.get(context).groupDatabase().updateMembers(groupID, members)
}
override fun setZombieMembers(groupID: String, members: List<Address>) {
DatabaseFactory.getGroupDatabase(context).updateZombieMembers(groupID, members)
DatabaseComponent.get(context).groupDatabase().updateZombieMembers(groupID, members)
}
override fun insertIncomingInfoMessage(context: Context, senderPublicKey: String, groupID: String, type: SignalServiceGroup.Type, name: String, members: Collection<String>, admins: Collection<String>, sentTimestamp: Long) {
@ -405,7 +406,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
val m = IncomingTextMessage(Address.fromSerialized(senderPublicKey), 1, sentTimestamp, "", Optional.of(group), 0, true)
val updateData = UpdateMessageData.buildGroupUpdate(type, name, members)?.toJSON()
val infoMessage = IncomingGroupMessage(m, groupID, updateData, true)
val smsDB = DatabaseFactory.getSmsDatabase(context)
val smsDB = DatabaseComponent.get(context).smsDatabase()
smsDB.insertMessageInbox(infoMessage)
}
@ -415,69 +416,69 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
val updateData = UpdateMessageData.buildGroupUpdate(type, name, members)?.toJSON() ?: ""
val infoMessage = OutgoingGroupMediaMessage(recipient, updateData, groupID, null, sentTimestamp, 0, true, null, listOf(), listOf())
val mmsDB = DatabaseFactory.getMmsDatabase(context)
val mmsSmsDB = DatabaseFactory.getMmsSmsDatabase(context)
val mmsDB = DatabaseComponent.get(context).mmsDatabase()
val mmsSmsDB = DatabaseComponent.get(context).mmsSmsDatabase()
if (mmsSmsDB.getMessageFor(sentTimestamp, userPublicKey) != null) return
val infoMessageID = mmsDB.insertMessageOutbox(infoMessage, threadID, false, null)
mmsDB.markAsSent(infoMessageID, true)
}
override fun isClosedGroup(publicKey: String): Boolean {
val isClosedGroup = DatabaseFactory.getLokiAPIDatabase(context).isClosedGroup(publicKey)
val isClosedGroup = DatabaseComponent.get(context).lokiAPIDatabase().isClosedGroup(publicKey)
val address = Address.fromSerialized(publicKey)
return address.isClosedGroup || isClosedGroup
}
override fun getClosedGroupEncryptionKeyPairs(groupPublicKey: String): MutableList<ECKeyPair> {
return DatabaseFactory.getLokiAPIDatabase(context).getClosedGroupEncryptionKeyPairs(groupPublicKey).toMutableList()
return DatabaseComponent.get(context).lokiAPIDatabase().getClosedGroupEncryptionKeyPairs(groupPublicKey).toMutableList()
}
override fun getLatestClosedGroupEncryptionKeyPair(groupPublicKey: String): ECKeyPair? {
return DatabaseFactory.getLokiAPIDatabase(context).getLatestClosedGroupEncryptionKeyPair(groupPublicKey)
return DatabaseComponent.get(context).lokiAPIDatabase().getLatestClosedGroupEncryptionKeyPair(groupPublicKey)
}
override fun getAllClosedGroupPublicKeys(): Set<String> {
return DatabaseFactory.getLokiAPIDatabase(context).getAllClosedGroupPublicKeys()
return DatabaseComponent.get(context).lokiAPIDatabase().getAllClosedGroupPublicKeys()
}
override fun getAllActiveClosedGroupPublicKeys(): Set<String> {
return DatabaseFactory.getLokiAPIDatabase(context).getAllClosedGroupPublicKeys().filter {
return DatabaseComponent.get(context).lokiAPIDatabase().getAllClosedGroupPublicKeys().filter {
getGroup(GroupUtil.doubleEncodeGroupID(it))?.isActive == true
}.toSet()
}
override fun addClosedGroupPublicKey(groupPublicKey: String) {
DatabaseFactory.getLokiAPIDatabase(context).addClosedGroupPublicKey(groupPublicKey)
DatabaseComponent.get(context).lokiAPIDatabase().addClosedGroupPublicKey(groupPublicKey)
}
override fun removeClosedGroupPublicKey(groupPublicKey: String) {
DatabaseFactory.getLokiAPIDatabase(context).removeClosedGroupPublicKey(groupPublicKey)
DatabaseComponent.get(context).lokiAPIDatabase().removeClosedGroupPublicKey(groupPublicKey)
}
override fun addClosedGroupEncryptionKeyPair(encryptionKeyPair: ECKeyPair, groupPublicKey: String) {
DatabaseFactory.getLokiAPIDatabase(context).addClosedGroupEncryptionKeyPair(encryptionKeyPair, groupPublicKey)
DatabaseComponent.get(context).lokiAPIDatabase().addClosedGroupEncryptionKeyPair(encryptionKeyPair, groupPublicKey)
}
override fun removeAllClosedGroupEncryptionKeyPairs(groupPublicKey: String) {
DatabaseFactory.getLokiAPIDatabase(context).removeAllClosedGroupEncryptionKeyPairs(groupPublicKey)
DatabaseComponent.get(context).lokiAPIDatabase().removeAllClosedGroupEncryptionKeyPairs(groupPublicKey)
}
override fun updateFormationTimestamp(groupID: String, formationTimestamp: Long) {
DatabaseFactory.getGroupDatabase(context)
DatabaseComponent.get(context).groupDatabase()
.updateFormationTimestamp(groupID, formationTimestamp)
}
override fun setExpirationTimer(groupID: String, duration: Int) {
val recipient = Recipient.from(context, fromSerialized(groupID), false)
DatabaseFactory.getRecipientDatabase(context).setExpireMessages(recipient, duration);
DatabaseComponent.get(context).recipientDatabase().setExpireMessages(recipient, duration);
}
override fun getAllV2OpenGroups(): Map<Long, OpenGroupV2> {
return DatabaseFactory.getLokiThreadDatabase(context).getAllV2OpenGroups()
return DatabaseComponent.get(context).lokiThreadDatabase().getAllV2OpenGroups()
}
override fun getAllGroups(): List<GroupRecord> {
return DatabaseFactory.getGroupDatabase(context).allGroups
return DatabaseComponent.get(context).groupDatabase().allGroups
}
override fun addOpenGroup(urlAsString: String) {
@ -486,16 +487,16 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
override fun setProfileSharing(address: Address, value: Boolean) {
val recipient = Recipient.from(context, address, false)
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, value)
DatabaseComponent.get(context).recipientDatabase().setProfileSharing(recipient, value)
}
override fun getOrCreateThreadIdFor(address: Address): Long {
val recipient = Recipient.from(context, address, false)
return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient)
return DatabaseComponent.get(context).threadDatabase().getOrCreateThreadIdFor(recipient)
}
override fun getOrCreateThreadIdFor(publicKey: String, groupPublicKey: String?, openGroupID: String?): Long {
val database = DatabaseFactory.getThreadDatabase(context)
val database = DatabaseComponent.get(context).threadDatabase()
if (!openGroupID.isNullOrEmpty()) {
val recipient = Recipient.from(context, Address.fromSerialized(GroupUtil.getEncodedOpenGroupID(openGroupID.toByteArray())), false)
return database.getThreadIdIfExistsFor(recipient)
@ -519,12 +520,12 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
override fun getThreadId(recipient: Recipient): Long? {
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(recipient)
val threadID = DatabaseComponent.get(context).threadDatabase().getThreadIdIfExistsFor(recipient)
return if (threadID < 0) null else threadID
}
override fun getThreadIdForMms(mmsId: Long): Long {
val mmsDb = DatabaseFactory.getMmsDatabase(context)
val mmsDb = DatabaseComponent.get(context).mmsDatabase()
val cursor = mmsDb.getMessage(mmsId)
val reader = mmsDb.readerFor(cursor)
val threadId = reader.next?.threadId
@ -533,29 +534,29 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
override fun getContactWithSessionID(sessionID: String): Contact? {
return DatabaseFactory.getSessionContactDatabase(context).getContactWithSessionID(sessionID)
return DatabaseComponent.get(context).sessionContactDatabase().getContactWithSessionID(sessionID)
}
override fun getAllContacts(): Set<Contact> {
return DatabaseFactory.getSessionContactDatabase(context).getAllContacts()
return DatabaseComponent.get(context).sessionContactDatabase().getAllContacts()
}
override fun setContact(contact: Contact) {
DatabaseFactory.getSessionContactDatabase(context).setContact(contact)
DatabaseComponent.get(context).sessionContactDatabase().setContact(contact)
}
override fun getRecipientForThread(threadId: Long): Recipient? {
return DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId)
return DatabaseComponent.get(context).threadDatabase().getRecipientForThreadId(threadId)
}
override fun getRecipientSettings(address: Address): Recipient.RecipientSettings? {
val recipientSettings = DatabaseFactory.getRecipientDatabase(context).getRecipientSettings(address)
val recipientSettings = DatabaseComponent.get(context).recipientDatabase().getRecipientSettings(address)
return if (recipientSettings.isPresent) { recipientSettings.get() } else null
}
override fun addContacts(contacts: List<ConfigurationMessage.Contact>) {
val recipientDatabase = DatabaseFactory.getRecipientDatabase(context)
val threadDatabase = DatabaseFactory.getThreadDatabase(context)
val recipientDatabase = DatabaseComponent.get(context).recipientDatabase()
val threadDatabase = DatabaseComponent.get(context).threadDatabase()
for (contact in contacts) {
val address = Address.fromSerialized(contact.publicKey)
val recipient = Recipient.from(context, address, true)
@ -579,12 +580,12 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
override fun getLastUpdated(threadID: Long): Long {
val threadDB = DatabaseFactory.getThreadDatabase(context)
val threadDB = DatabaseComponent.get(context).threadDatabase()
return threadDB.getLastUpdated(threadID)
}
override fun trimThread(threadID: Long, threadLimit: Int) {
val threadDB = DatabaseFactory.getThreadDatabase(context)
val threadDB = DatabaseComponent.get(context).threadDatabase()
threadDB.trimThread(threadID, threadLimit)
}
@ -597,7 +598,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
}
override fun insertDataExtractionNotificationMessage(senderPublicKey: String, message: DataExtractionNotificationInfoMessage, sentTimestamp: Long) {
val database = DatabaseFactory.getMmsDatabase(context)
val database = DatabaseComponent.get(context).mmsDatabase()
val address = fromSerialized(senderPublicKey)
val recipient = Recipient.from(context, address, false)

View File

@ -49,6 +49,7 @@ import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.util.SessionMetaProtocol;
@ -241,7 +242,7 @@ public class ThreadDatabase extends Database {
Cursor cursor = null;
try {
cursor = DatabaseFactory.getMmsSmsDatabase(context).getConversation(threadId);
cursor = DatabaseComponent.get(context).mmsSmsDatabase().getConversation(threadId);
if (cursor != null && length > 0 && cursor.getCount() > length) {
Log.w("ThreadDatabase", "Cursor count is greater than length!");
@ -251,8 +252,8 @@ public class ThreadDatabase extends Database {
Log.i("ThreadDatabase", "Cut off tweet date: " + lastTweetDate);
DatabaseFactory.getSmsDatabase(context).deleteMessagesInThreadBeforeDate(threadId, lastTweetDate);
DatabaseFactory.getMmsDatabase(context).deleteMessagesInThreadBeforeDate(threadId, lastTweetDate);
DatabaseComponent.get(context).smsDatabase().deleteMessagesInThreadBeforeDate(threadId, lastTweetDate);
DatabaseComponent.get(context).mmsDatabase().deleteMessagesInThreadBeforeDate(threadId, lastTweetDate);
update(threadId, false);
notifyConversationListeners(threadId);
@ -275,8 +276,8 @@ public class ThreadDatabase extends Database {
SQLiteDatabase db = databaseHelper.getWritableDatabase();
db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {threadId+""});
final List<MarkedMessageInfo> smsRecords = DatabaseFactory.getSmsDatabase(context).setMessagesRead(threadId);
final List<MarkedMessageInfo> mmsRecords = DatabaseFactory.getMmsDatabase(context).setMessagesRead(threadId);
final List<MarkedMessageInfo> smsRecords = DatabaseComponent.get(context).smsDatabase().setMessagesRead(threadId);
final List<MarkedMessageInfo> mmsRecords = DatabaseComponent.get(context).mmsDatabase().setMessagesRead(threadId);
notifyConversationListListeners();
@ -428,10 +429,10 @@ public class ThreadDatabase extends Database {
}
public void deleteConversation(long threadId) {
DatabaseFactory.getSmsDatabase(context).deleteThread(threadId);
DatabaseFactory.getMmsDatabase(context).deleteThread(threadId);
DatabaseFactory.getDraftDatabase(context).clearDrafts(threadId);
DatabaseFactory.getLokiMessageDatabase(context).deleteThread(threadId);
DatabaseComponent.get(context).smsDatabase().deleteThread(threadId);
DatabaseComponent.get(context).mmsDatabase().deleteThread(threadId);
DatabaseComponent.get(context).draftDatabase().clearDrafts(threadId);
DatabaseComponent.get(context).lokiMessageDatabase().deleteThread(threadId);
deleteThread(threadId);
notifyConversationListeners(threadId);
notifyConversationListListeners();
@ -485,7 +486,7 @@ public class ThreadDatabase extends Database {
if (cursor != null && cursor.moveToFirst()) {
return cursor.getLong(cursor.getColumnIndexOrThrow(ID));
} else {
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, true);
DatabaseComponent.get(context).recipientDatabase().setProfileSharing(recipient, true);
return createThreadForRecipient(recipient.getAddress(), recipient.isGroupRecipient(), distributionType);
}
} finally {
@ -529,7 +530,7 @@ public class ThreadDatabase extends Database {
}
public boolean update(long threadId, boolean unarchive) {
MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context);
MmsSmsDatabase mmsSmsDatabase = DatabaseComponent.get(context).mmsSmsDatabase();
long count = mmsSmsDatabase.getConversationCount(threadId);
boolean shouldDeleteEmptyThread = deleteThreadOnEmpty(threadId);
@ -657,8 +658,8 @@ public class ThreadDatabase extends Database {
Optional<GroupRecord> groupRecord;
if (distributionType != DistributionTypes.ARCHIVE && distributionType != DistributionTypes.INBOX_ZERO) {
settings = DatabaseFactory.getRecipientDatabase(context).getRecipientSettings(cursor);
groupRecord = DatabaseFactory.getGroupDatabase(context).getGroup(cursor);
settings = DatabaseComponent.get(context).recipientDatabase().getRecipientSettings(cursor);
groupRecord = DatabaseComponent.get(context).groupDatabase().getGroup(cursor);
} else {
settings = Optional.absent();
groupRecord = Optional.absent();

View File

@ -4,16 +4,16 @@ package org.thoughtcrime.securesms.database.loaders;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import androidx.annotation.NonNull;
import androidx.loader.content.AsyncTaskLoader;
import com.annimon.stream.Stream;
import network.loki.messenger.R;
import org.session.libsession.utilities.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MediaDatabase;
import org.session.libsession.utilities.recipients.Recipient;
import org.thoughtcrime.securesms.database.MediaDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@ -26,6 +26,8 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import network.loki.messenger.R;
public class BucketedThreadMediaLoader extends AsyncTaskLoader<BucketedThreadMediaLoader.BucketedThreadMedia> {
@SuppressWarnings("unused")
@ -56,16 +58,18 @@ public class BucketedThreadMediaLoader extends AsyncTaskLoader<BucketedThreadMed
@Override
protected void onAbandon() {
DatabaseFactory.getMediaDatabase(getContext()).unsubscribeToMediaChanges(observer);
DatabaseComponent.get(getContext()).mediaDatabase().unsubscribeToMediaChanges(observer);
}
@Override
public BucketedThreadMedia loadInBackground() {
BucketedThreadMedia result = new BucketedThreadMedia(getContext());
long threadId = DatabaseFactory.getThreadDatabase(getContext()).getOrCreateThreadIdFor(Recipient.from(getContext(), address, true));
long threadId = DatabaseComponent.get(getContext()).threadDatabase().getOrCreateThreadIdFor(Recipient.from(getContext(), address, true));
DatabaseFactory.getMediaDatabase(getContext()).subscribeToMediaChanges(observer);
try (Cursor cursor = DatabaseFactory.getMediaDatabase(getContext()).getGalleryMediaForThread(threadId)) {
MediaDatabase mediaDatabase = DatabaseComponent.get(getContext()).mediaDatabase();
mediaDatabase.subscribeToMediaChanges(observer);
try (Cursor cursor = mediaDatabase.getGalleryMediaForThread(threadId)) {
while (cursor != null && cursor.moveToNext()) {
result.add(MediaDatabase.MediaRecord.from(getContext(), cursor));
}

View File

@ -1,58 +0,0 @@
package org.thoughtcrime.securesms.database.loaders;
import android.content.Context;
import android.database.Cursor;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.util.AbstractCursorLoader;
import org.session.libsignal.utilities.Pair;
public class ConversationLoader extends AbstractCursorLoader {
private final long threadId;
private int offset;
private int limit;
private long lastSeen;
private boolean hasSent;
public ConversationLoader(Context context, long threadId, int offset, int limit, long lastSeen) {
super(context);
this.threadId = threadId;
this.offset = offset;
this.limit = limit;
this.lastSeen = lastSeen;
this.hasSent = true;
}
public boolean hasLimit() {
return limit > 0;
}
public boolean hasOffset() {
return offset > 0;
}
public int getOffset() {
return offset;
}
public long getLastSeen() {
return lastSeen;
}
public boolean hasSent() {
return hasSent;
}
@Override
public Cursor getCursor() {
Pair<Long, Boolean> lastSeenAndHasSent = DatabaseFactory.getThreadDatabase(context).getLastSeenAndHasSent(threadId);
this.hasSent = lastSeenAndHasSent.second();
if (lastSeen == -1) {
this.lastSeen = lastSeenAndHasSent.first();
}
return DatabaseFactory.getMmsSmsDatabase(context).getConversation(threadId, offset, limit);
}
}

View File

@ -1,47 +0,0 @@
/**
* Copyright (C) 2015 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.database.loaders;
import android.content.Context;
import android.database.Cursor;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
import org.thoughtcrime.securesms.util.AbstractCursorLoader;
public class MessageDetailsLoader extends AbstractCursorLoader {
private final String type;
private final long messageId;
public MessageDetailsLoader(Context context, String type, long messageId) {
super(context);
this.type = type;
this.messageId = messageId;
}
@Override
public Cursor getCursor() {
switch (type) {
case MmsSmsDatabase.SMS_TRANSPORT:
return DatabaseFactory.getSmsDatabase(context).getMessageCursor(messageId);
case MmsSmsDatabase.MMS_TRANSPORT:
return DatabaseFactory.getMmsDatabase(context).getMessage(messageId);
default:
throw new AssertionError("no valid message type specified");
}
}
}

View File

@ -4,15 +4,16 @@ package org.thoughtcrime.securesms.database.loaders;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.util.Pair;
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.session.libsession.utilities.recipients.Recipient;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.util.AsyncLoader;
public class PagingMediaLoader extends AsyncLoader<Pair<Cursor, Integer>> {
@ -34,8 +35,8 @@ public class PagingMediaLoader extends AsyncLoader<Pair<Cursor, Integer>> {
@Nullable
@Override
public Pair<Cursor, Integer> loadInBackground() {
long threadId = DatabaseFactory.getThreadDatabase(getContext()).getOrCreateThreadIdFor(recipient);
Cursor cursor = DatabaseFactory.getMediaDatabase(getContext()).getGalleryMediaForThread(threadId);
long threadId = DatabaseComponent.get(getContext()).threadDatabase().getOrCreateThreadIdFor(recipient);
Cursor cursor = DatabaseComponent.get(getContext()).mediaDatabase().getGalleryMediaForThread(threadId);
while (cursor != null && cursor.moveToNext()) {
AttachmentId attachmentId = new AttachmentId(cursor.getLong(cursor.getColumnIndexOrThrow(AttachmentDatabase.ROW_ID)), cursor.getLong(cursor.getColumnIndexOrThrow(AttachmentDatabase.UNIQUE_ID)));

View File

@ -3,11 +3,12 @@ package org.thoughtcrime.securesms.database.loaders;
import android.content.Context;
import android.database.Cursor;
import androidx.annotation.NonNull;
import org.session.libsession.utilities.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.session.libsession.utilities.recipients.Recipient;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.util.AbstractCursorLoader;
public class ThreadMediaLoader extends AbstractCursorLoader {
@ -23,10 +24,10 @@ public class ThreadMediaLoader extends AbstractCursorLoader {
@Override
public Cursor getCursor() {
long threadId = DatabaseFactory.getThreadDatabase(getContext()).getOrCreateThreadIdFor(Recipient.from(getContext(), address, true));
long threadId = DatabaseComponent.get(context).threadDatabase().getOrCreateThreadIdFor(Recipient.from(getContext(), address, true));
if (gallery) return DatabaseFactory.getMediaDatabase(getContext()).getGalleryMediaForThread(threadId);
else return DatabaseFactory.getMediaDatabase(getContext()).getDocumentMediaForThread(threadId);
if (gallery) return DatabaseComponent.get(context).mediaDatabase().getGalleryMediaForThread(threadId);
else return DatabaseComponent.get(context).mediaDatabase().getDocumentMediaForThread(threadId);
}
public Address getAddress() {

View File

@ -0,0 +1,45 @@
package org.thoughtcrime.securesms.dependencies
import android.content.Context
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.session.libsession.database.MessageDataProvider
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.database.*
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
@EntryPoint
@InstallIn(SingletonComponent::class)
interface DatabaseComponent {
companion object {
@JvmStatic
fun get(context: Context) = ApplicationContext.getInstance(context).databaseComponent
}
fun openHelper(): SQLCipherOpenHelper
fun smsDatabase(): SmsDatabase
fun mmsDatabase(): MmsDatabase
fun attachmentDatabase(): AttachmentDatabase
fun mediaDatabase(): MediaDatabase
fun threadDatabase(): ThreadDatabase
fun mmsSmsDatabase(): MmsSmsDatabase
fun draftDatabase(): DraftDatabase
fun pushDatabase(): PushDatabase
fun groupDatabase(): GroupDatabase
fun recipientDatabase(): RecipientDatabase
fun groupReceiptDatabase(): GroupReceiptDatabase
fun searchDatabase(): SearchDatabase
fun jobDatabase(): JobDatabase
fun lokiAPIDatabase(): LokiAPIDatabase
fun lokiMessageDatabase(): LokiMessageDatabase
fun lokiThreadDatabase(): LokiThreadDatabase
fun lokiUserDatabase(): LokiUserDatabase
fun lokiBackupFilesDatabase(): LokiBackupFilesDatabase
fun sessionJobDatabase(): SessionJobDatabase
fun sessionContactDatabase(): SessionContactDatabase
fun storage(): Storage
fun attachmentProvider(): MessageDataProvider
}

View File

@ -0,0 +1,128 @@
package org.thoughtcrime.securesms.dependencies
import android.content.Context
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import net.sqlcipher.database.SQLiteDatabase
import org.session.libsession.database.MessageDataProvider
import org.thoughtcrime.securesms.attachments.DatabaseAttachmentProvider
import org.thoughtcrime.securesms.crypto.AttachmentSecret
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider
import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider
import org.thoughtcrime.securesms.database.*
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {
@JvmStatic
fun init(context: Context) {
SQLiteDatabase.loadLibs(context)
}
@Provides
@Singleton
fun provideAttachmentSecret(@ApplicationContext context: Context) = AttachmentSecretProvider.getInstance(context).orCreateAttachmentSecret
@Provides
@Singleton
fun provideOpenHelper(@ApplicationContext context: Context): SQLCipherOpenHelper {
val dbSecret = DatabaseSecretProvider(context).orCreateDatabaseSecret
return SQLCipherOpenHelper(context, dbSecret)
}
@Provides
@Singleton
fun provideSmsDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = SmsDatabase(context, openHelper)
@Provides
@Singleton
fun provideMmsDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = MmsDatabase(context, openHelper)
@Provides
@Singleton
fun provideAttachmentDatabase(@ApplicationContext context: Context,
openHelper: SQLCipherOpenHelper,
attachmentSecret: AttachmentSecret) = AttachmentDatabase(context, openHelper, attachmentSecret)
@Provides
@Singleton
fun provideMediaDatbase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = MediaDatabase(context, openHelper)
@Provides
@Singleton
fun provideThread(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = ThreadDatabase(context,openHelper)
@Provides
@Singleton
fun provideMmsSms(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = MmsSmsDatabase(context, openHelper)
@Provides
@Singleton
fun provideDraftDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = DraftDatabase(context, openHelper)
@Provides
@Singleton
fun providePushDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = PushDatabase(context,openHelper)
@Provides
@Singleton
fun provideGroupDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = GroupDatabase(context,openHelper)
@Provides
@Singleton
fun provideRecipientDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = RecipientDatabase(context,openHelper)
@Provides
@Singleton
fun provideGroupReceiptDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = GroupReceiptDatabase(context,openHelper)
@Provides
@Singleton
fun searchDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = SearchDatabase(context,openHelper)
@Provides
@Singleton
fun provideJobDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = JobDatabase(context, openHelper)
@Provides
@Singleton
fun provideLokiApiDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = LokiAPIDatabase(context,openHelper)
@Provides
@Singleton
fun provideLokiMessageDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = LokiMessageDatabase(context,openHelper)
@Provides
@Singleton
fun provideLokiThreadDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = LokiThreadDatabase(context,openHelper)
@Provides
@Singleton
fun provideLokiUserDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = LokiUserDatabase(context,openHelper)
@Provides
@Singleton
fun provideLokiBackupFilesDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = LokiBackupFilesDatabase(context,openHelper)
@Provides
@Singleton
fun provideSessionJobDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = SessionJobDatabase(context, openHelper)
@Provides
@Singleton
fun provideSessionContactDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = SessionContactDatabase(context,openHelper)
@Provides
@Singleton
fun provideStorage(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = Storage(context,openHelper)
@Provides
@Singleton
fun provideAttachmentProvider(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper): MessageDataProvider = DatabaseAttachmentProvider(context, openHelper)
}

View File

@ -1,24 +0,0 @@
package org.thoughtcrime.securesms.dependencies;
import android.content.Context;
import org.thoughtcrime.securesms.jobs.AvatarDownloadJob;
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment;
import dagger.Module;
@Module(complete = false, injects = {AvatarDownloadJob.class,
RetrieveProfileAvatarJob.class,
AppProtectionPreferenceFragment.class,
LinkPreviewRepository.class})
public class SignalCommunicationModule {
private final Context context;
public SignalCommunicationModule(Context context) {
this.context = context;
}
}

View File

@ -29,7 +29,7 @@ import org.session.libsignal.utilities.PublicKeyValidation
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.util.ScanQRCodeWrapperFragment
import org.thoughtcrime.securesms.util.ScanQRCodeWrapperFragmentDelegate
@ -113,7 +113,7 @@ class CreatePrivateChatActivity : PassphraseRequiredActionBarActivity(), ScanQRC
val intent = Intent(this, ConversationActivityV2::class.java)
intent.putExtra(ConversationActivityV2.ADDRESS, recipient.address)
intent.setDataAndType(getIntent().data, getIntent().type)
val existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient)
val existingThread = DatabaseComponent.get(this).threadDatabase().getThreadIdIfExistsFor(recipient)
intent.putExtra(ConversationActivityV2.THREAD_ID, existingThread)
startActivity(intent)
finish()

View File

@ -3,31 +3,30 @@ package org.thoughtcrime.securesms.groups
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.loader.app.LoaderManager
import androidx.loader.content.Loader
import androidx.recyclerview.widget.LinearLayoutManager
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.Toast
import androidx.loader.app.LoaderManager
import androidx.loader.content.Loader
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_create_closed_group.*
import network.loki.messenger.R
import nl.komponents.kovenant.ui.failUi
import nl.komponents.kovenant.ui.successUi
import org.session.libsession.messaging.sending_receiving.MessageSender
import org.session.libsession.messaging.sending_receiving.groupSizeLimit
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.session.libsession.utilities.Address
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.util.fadeIn
import org.thoughtcrime.securesms.util.fadeOut
import org.thoughtcrime.securesms.mms.GlideApp
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.contacts.SelectContactsAdapter
import org.thoughtcrime.securesms.contacts.SelectContactsLoader
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.mms.GlideApp
import org.thoughtcrime.securesms.util.fadeIn
import org.thoughtcrime.securesms.util.fadeOut
//TODO Refactor to avoid using kotlinx.android.synthetic
class CreateClosedGroupActivity : PassphraseRequiredActionBarActivity(), LoaderManager.LoaderCallbacks<List<String>> {
@ -121,7 +120,7 @@ class CreateClosedGroupActivity : PassphraseRequiredActionBarActivity(), LoaderM
MessageSender.createClosedGroup(name.toString(), selectedMembers + setOf( userPublicKey )).successUi { groupID ->
loaderContainer.fadeOut()
isLoading = false
val threadID = DatabaseFactory.getThreadDatabase(this).getOrCreateThreadIdFor(Recipient.from(this, Address.fromSerialized(groupID), false))
val threadID = DatabaseComponent.get(this).threadDatabase().getOrCreateThreadIdFor(Recipient.from(this, Address.fromSerialized(groupID), false))
if (!isFinishing) {
openConversationActivity(this, threadID, Recipient.from(this, Address.fromSerialized(groupID), false))
finish()

View File

@ -21,18 +21,18 @@ import nl.komponents.kovenant.ui.failUi
import nl.komponents.kovenant.ui.successUi
import org.session.libsession.messaging.sending_receiving.MessageSender
import org.session.libsession.messaging.sending_receiving.groupSizeLimit
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.session.libsession.utilities.Address
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.util.fadeIn
import org.thoughtcrime.securesms.util.fadeOut
import org.thoughtcrime.securesms.mms.GlideApp
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsession.utilities.GroupUtil
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.ThemeUtil
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsignal.utilities.toHexString
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.contacts.SelectContactsActivity
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.mms.GlideApp
import org.thoughtcrime.securesms.util.fadeIn
import org.thoughtcrime.securesms.util.fadeOut
import java.io.IOException
class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
@ -90,7 +90,7 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
ThemeUtil.getThemedDrawableResId(this, R.attr.actionModeCloseDrawable))
groupID = intent.getStringExtra(groupIDKey)!!
val groupInfo = DatabaseFactory.getGroupDatabase(this).getGroup(groupID).get()
val groupInfo = DatabaseComponent.get(this).groupDatabase().getGroup(groupID).get()
originalName = groupInfo.title
isSelfAdmin = groupInfo.admins.any{ it.serialize() == TextSecurePreferences.getLocalNumber(this) }
@ -260,7 +260,7 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
var groupPublicKey: String?
try {
groupPublicKey = GroupUtil.doubleDecodeGroupID(groupID).toHexString()
isClosedGroup = DatabaseFactory.getLokiAPIDatabase(this).isClosedGroup(groupPublicKey)
isClosedGroup = DatabaseComponent.get(this).lokiAPIDatabase().isClosedGroup(groupPublicKey)
} catch (e: IOException) {
groupPublicKey = null
isClosedGroup = false

View File

@ -1,13 +1,13 @@
package org.thoughtcrime.securesms.groups
import android.content.Context
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.util.AsyncLoader
class EditClosedGroupLoader(context: Context, val groupID: String) : AsyncLoader<EditClosedGroupActivity.GroupMembers>(context) {
override fun loadInBackground(): EditClosedGroupActivity.GroupMembers {
val groupDatabase = DatabaseFactory.getGroupDatabase(context)
val groupDatabase = DatabaseComponent.get(context).groupDatabase()
val members = groupDatabase.getGroupMembers(groupID, true)
val zombieMembers = groupDatabase.getGroupZombieMembers(groupID)
return EditClosedGroupActivity.GroupMembers(

View File

@ -8,13 +8,12 @@ import androidx.annotation.Nullable;
import org.session.libsession.utilities.Address;
import org.session.libsession.utilities.DistributionTypes;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsession.utilities.GroupUtil;
import org.session.libsession.utilities.TextSecurePreferences;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.session.libsession.utilities.recipients.Recipient;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.util.BitmapUtil;
import java.util.HashSet;
@ -31,7 +30,7 @@ public class GroupManager {
public static long getThreadIDFromGroupID(String groupID, @NonNull Context context) {
final Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupID), false);
return DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(groupRecipient);
return DatabaseComponent.get(context).threadDatabase().getThreadIdIfExistsFor(groupRecipient);
}
public static @NonNull GroupActionResult createOpenGroup(@NonNull String id,
@ -49,7 +48,7 @@ public class GroupManager {
@Nullable String name)
{
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
final GroupDatabase groupDatabase = DatabaseComponent.get(context).groupDatabase();
final Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), false);
final Set<Address> memberAddresses = new HashSet<>();
@ -58,7 +57,7 @@ public class GroupManager {
groupDatabase.updateProfilePicture(groupId, avatarBytes);
long threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(
long threadID = DatabaseComponent.get(context).threadDatabase().getOrCreateThreadIdFor(
groupRecipient, DistributionTypes.CONVERSATION);
return new GroupActionResult(groupRecipient, threadID);
}
@ -66,8 +65,8 @@ public class GroupManager {
public static boolean deleteGroup(@NonNull String groupId,
@NonNull Context context)
{
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
final ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
final GroupDatabase groupDatabase = DatabaseComponent.get(context).groupDatabase();
final ThreadDatabase threadDatabase = DatabaseComponent.get(context).threadDatabase();
final Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), false);
long threadId = threadDatabase.getThreadIdIfExistsFor(groupRecipient);

View File

@ -10,7 +10,7 @@ import org.session.libsession.messaging.open_groups.OpenGroupV2
import org.session.libsession.messaging.sending_receiving.pollers.OpenGroupPollerV2
import org.session.libsession.utilities.Util
import org.session.libsignal.utilities.ThreadUtils
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.util.BitmapUtil
import java.util.concurrent.Executors
@ -59,7 +59,7 @@ object OpenGroupManager {
val openGroupID = "$server.$room"
var threadID = GroupManager.getOpenGroupThreadID(openGroupID, context)
val storage = MessagingModuleConfiguration.shared.storage
val threadDB = DatabaseFactory.getLokiThreadDatabase(context)
val threadDB = DatabaseComponent.get(context).lokiThreadDatabase()
// Check it it's added already
val existingOpenGroup = threadDB.getOpenGroupChat(threadID)
if (existingOpenGroup != null) { return }
@ -97,7 +97,7 @@ object OpenGroupManager {
fun delete(server: String, room: String, context: Context) {
val storage = MessagingModuleConfiguration.shared.storage
val threadDB = DatabaseFactory.getThreadDatabase(context)
val threadDB = DatabaseComponent.get(context).threadDatabase()
val openGroupID = "$server.$room"
val threadID = GroupManager.getOpenGroupThreadID(openGroupID, context)
val recipient = threadDB.getRecipientForThreadId(threadID) ?: return
@ -112,7 +112,7 @@ object OpenGroupManager {
// Delete
storage.removeLastDeletionServerID(room, server)
storage.removeLastMessageServerID(room, server)
val lokiThreadDB = DatabaseFactory.getLokiThreadDatabase(context)
val lokiThreadDB = DatabaseComponent.get(context).lokiThreadDatabase()
lokiThreadDB.removeOpenGroupChat(threadID)
ThreadUtils.queue {
threadDB.deleteConversation(threadID) // Must be invoked on a background thread

View File

@ -4,9 +4,9 @@ import android.content.Context
import androidx.annotation.WorkerThread
import org.greenrobot.eventbus.EventBus
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsession.utilities.GroupUtil
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import java.util.*
//TODO Refactor so methods declare specific type of checked exceptions and not generalized Exception.
@ -25,7 +25,7 @@ object OpenGroupUtilities {
@Throws(Exception::class)
fun updateGroupInfo(context: Context, server: String, room: String) {
val groupId = GroupUtil.getEncodedOpenGroupID("$server.$room".toByteArray())
if (!DatabaseFactory.getGroupDatabase(context).hasGroup(groupId)) {
if (!DatabaseComponent.get(context).groupDatabase().hasGroup(groupId)) {
throw IllegalStateException("Attempt to update open group info for non-existent DB record: $groupId")
}

View File

@ -19,6 +19,7 @@ import androidx.loader.app.LoaderManager
import androidx.loader.content.Loader
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.recyclerview.widget.LinearLayoutManager
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.android.synthetic.main.activity_home.*
import kotlinx.android.synthetic.main.seed_reminder_stub.*
import kotlinx.android.synthetic.main.seed_reminder_stub.view.*
@ -42,8 +43,11 @@ import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.conversation.v2.utilities.NotificationUtils
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.GroupDatabase
import org.thoughtcrime.securesms.database.RecipientDatabase
import org.thoughtcrime.securesms.database.ThreadDatabase
import org.thoughtcrime.securesms.database.model.ThreadRecord
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.dms.CreatePrivateChatActivity
import org.thoughtcrime.securesms.groups.CreateClosedGroupActivity
import org.thoughtcrime.securesms.groups.JoinPublicChatActivity
@ -56,11 +60,17 @@ import org.thoughtcrime.securesms.preferences.SettingsActivity
import org.thoughtcrime.securesms.util.*
import java.io.IOException
import java.util.*
import javax.inject.Inject
@AndroidEntryPoint
class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickListener, SeedReminderViewDelegate, NewConversationButtonSetViewDelegate {
private lateinit var glide: GlideRequests
private var broadcastReceiver: BroadcastReceiver? = null
@Inject lateinit var threadDb: ThreadDatabase
@Inject lateinit var recipientDatabase: RecipientDatabase
@Inject lateinit var groupDatabase: GroupDatabase
private val publicKey: String
get() = TextSecurePreferences.getLocalNumber(this)!!
@ -94,7 +104,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis
seedReminderStub.isVisible = false
}
// Set up recycler view
val cursor = DatabaseFactory.getThreadDatabase(this).conversationList
val cursor = threadDb.conversationList
val homeAdapter = HomeAdapter(this, cursor)
homeAdapter.setHasStableIds(true)
homeAdapter.glide = glide
@ -280,7 +290,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.RecipientPreferenceActivity_block) { dialog, _ ->
ThreadUtils.queue {
DatabaseFactory.getRecipientDatabase(this).setBlocked(thread.recipient, true)
recipientDatabase.setBlocked(thread.recipient, true)
Util.runOnMain {
recyclerView.adapter!!.notifyDataSetChanged()
dialog.dismiss()
@ -296,7 +306,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.RecipientPreferenceActivity_unblock) { dialog, _ ->
ThreadUtils.queue {
DatabaseFactory.getRecipientDatabase(this).setBlocked(thread.recipient, false)
recipientDatabase.setBlocked(thread.recipient, false)
Util.runOnMain {
recyclerView.adapter!!.notifyDataSetChanged()
dialog.dismiss()
@ -308,7 +318,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis
private fun setConversationMuted(thread: ThreadRecord, isMuted: Boolean) {
if (!isMuted) {
ThreadUtils.queue {
DatabaseFactory.getRecipientDatabase(this).setMuted(thread.recipient, 0)
recipientDatabase.setMuted(thread.recipient, 0)
Util.runOnMain {
recyclerView.adapter!!.notifyDataSetChanged()
}
@ -316,7 +326,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis
} else {
MuteDialog.show(this) { until: Long ->
ThreadUtils.queue {
DatabaseFactory.getRecipientDatabase(this).setMuted(thread.recipient, until)
recipientDatabase.setMuted(thread.recipient, until)
Util.runOnMain {
recyclerView.adapter!!.notifyDataSetChanged()
}
@ -327,7 +337,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis
private fun setNotifyType(thread: ThreadRecord, newNotifyType: Int) {
ThreadUtils.queue {
DatabaseFactory.getRecipientDatabase(this).setNotifyType(thread.recipient, newNotifyType)
recipientDatabase.setNotifyType(thread.recipient, newNotifyType)
Util.runOnMain {
recyclerView.adapter!!.notifyDataSetChanged()
}
@ -337,10 +347,9 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis
private fun deleteConversation(thread: ThreadRecord) {
val threadID = thread.threadId
val recipient = thread.recipient
val threadDB = DatabaseFactory.getThreadDatabase(this)
val message: String
if (recipient.isGroupRecipient) {
val group = DatabaseFactory.getGroupDatabase(this).getGroup(recipient.address.toString()).orNull()
val group = groupDatabase.getGroup(recipient.address.toString()).orNull()
if (group != null && group.admins.map { it.toString() }.contains(TextSecurePreferences.getLocalNumber(this))) {
message = "Because you are the creator of this group it will be deleted for everyone. This cannot be undone."
} else {
@ -355,14 +364,14 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis
lifecycleScope.launch(Dispatchers.Main) {
val context = this@HomeActivity as Context
// Cancel any outstanding jobs
DatabaseFactory.getSessionJobDatabase(context).cancelPendingMessageSendJobs(threadID)
DatabaseComponent.get(context).sessionJobDatabase().cancelPendingMessageSendJobs(threadID)
// Send a leave group message if this is an active closed group
if (recipient.address.isClosedGroup && DatabaseFactory.getGroupDatabase(context).isActive(recipient.address.toGroupString())) {
if (recipient.address.isClosedGroup && DatabaseComponent.get(context).groupDatabase().isActive(recipient.address.toGroupString())) {
var isClosedGroup: Boolean
var groupPublicKey: String?
try {
groupPublicKey = GroupUtil.doubleDecodeGroupID(recipient.address.toString()).toHexString()
isClosedGroup = DatabaseFactory.getLokiAPIDatabase(context).isClosedGroup(groupPublicKey)
isClosedGroup = DatabaseComponent.get(context).lokiAPIDatabase().isClosedGroup(groupPublicKey)
} catch (e: IOException) {
groupPublicKey = null
isClosedGroup = false
@ -372,12 +381,12 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis
}
}
// Delete the conversation
val v2OpenGroup = DatabaseFactory.getLokiThreadDatabase(context).getOpenGroupChat(threadID)
val v2OpenGroup = DatabaseComponent.get(this@HomeActivity).lokiThreadDatabase().getOpenGroupChat(threadID)
if (v2OpenGroup != null) {
OpenGroupManager.delete(v2OpenGroup.server, v2OpenGroup.room, this@HomeActivity)
} else {
ThreadUtils.queue {
threadDB.deleteConversation(threadID)
threadDb.deleteConversation(threadID)
}
}
// Update the badge count

View File

@ -2,15 +2,15 @@ package org.thoughtcrime.securesms.home
import android.content.Context
import android.database.Cursor
import androidx.recyclerview.widget.RecyclerView
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.model.ThreadRecord
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.mms.GlideRequests
class HomeAdapter(context: Context, cursor: Cursor?) : CursorRecyclerViewAdapter<HomeAdapter.ViewHolder>(context, cursor) {
private val threadDatabase = DatabaseFactory.getThreadDatabase(context)
private val threadDatabase = DatabaseComponent.get(context).threadDatabase()
lateinit var glide: GlideRequests
var typingThreadIDs = setOf<Long>()
set(value) { field = value; notifyDataSetChanged() }

View File

@ -2,12 +2,12 @@ package org.thoughtcrime.securesms.home
import android.content.Context
import android.database.Cursor
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.util.AbstractCursorLoader
class HomeLoader(context: Context) : AbstractCursorLoader(context) {
override fun getCursor(): Cursor {
return DatabaseFactory.getThreadDatabase(context).conversationList
return DatabaseComponent.get(context).threadDatabase().conversationList
}
}

View File

@ -20,7 +20,7 @@ import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.mms.GlideApp
import org.thoughtcrime.securesms.util.UiModeUtilities
@ -103,7 +103,7 @@ class UserDetailsBottomSheet : BottomSheetDialogFragment() {
newNickName = nicknameEditText.text.toString()
}
val publicKey = recipient.address.serialize()
val contactDB = DatabaseFactory.getSessionContactDatabase(context)
val contactDB = DatabaseComponent.get(requireContext()).sessionContactDatabase()
val contact = contactDB.getContactWithSessionID(publicKey) ?: Contact(publicKey)
contact.nickname = newNickName
contactDB.setContact(contact)

View File

@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.jobmanager;
import android.app.Application;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
@ -8,13 +9,13 @@ import androidx.annotation.WorkerThread;
import com.annimon.stream.Stream;
import org.session.libsession.messaging.utilities.Data;
import org.session.libsession.utilities.Debouncer;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.jobmanager.persistence.ConstraintSpec;
import org.thoughtcrime.securesms.jobmanager.persistence.DependencySpec;
import org.thoughtcrime.securesms.jobmanager.persistence.FullSpec;
import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec;
import org.thoughtcrime.securesms.jobmanager.persistence.JobStorage;
import org.session.libsignal.utilities.Log;
import org.session.libsession.utilities.Debouncer;
import java.util.ArrayList;
import java.util.Collections;
@ -37,7 +38,6 @@ class JobController {
private final JobInstantiator jobInstantiator;
private final ConstraintInstantiator constraintInstantiator;
private final Data.Serializer dataSerializer;
private final DependencyInjector dependencyInjector;
private final Scheduler scheduler;
private final Debouncer debouncer;
private final Callback callback;
@ -48,7 +48,6 @@ class JobController {
@NonNull JobInstantiator jobInstantiator,
@NonNull ConstraintInstantiator constraintInstantiator,
@NonNull Data.Serializer dataSerializer,
@NonNull DependencyInjector dependencyInjector,
@NonNull Scheduler scheduler,
@NonNull Debouncer debouncer,
@NonNull Callback callback)
@ -58,7 +57,6 @@ class JobController {
this.jobInstantiator = jobInstantiator;
this.constraintInstantiator = constraintInstantiator;
this.dataSerializer = dataSerializer;
this.dependencyInjector = dependencyInjector;
this.scheduler = scheduler;
this.debouncer = debouncer;
this.callback = callback;
@ -329,8 +327,6 @@ class JobController {
job.setNextRunAttemptTime(jobSpec.getNextRunAttemptTime());
job.setContext(application);
dependencyInjector.injectDependencies(job);
return job;
}

View File

@ -3,14 +3,15 @@ package org.thoughtcrime.securesms.jobmanager;
import android.app.Application;
import android.content.Intent;
import android.os.Build;
import androidx.annotation.NonNull;
import org.session.libsession.messaging.utilities.Data;
import org.session.libsession.utilities.Debouncer;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.jobmanager.impl.DefaultExecutorFactory;
import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer;
import org.thoughtcrime.securesms.jobmanager.persistence.JobStorage;
import org.session.libsignal.utilities.Log;
import org.session.libsession.utilities.Debouncer;
import java.util.ArrayList;
import java.util.Collections;
@ -45,7 +46,6 @@ public class JobManager implements ConstraintObserver.Notifier {
configuration.getJobInstantiator(),
configuration.getConstraintFactories(),
configuration.getDataSerializer(),
configuration.getDependencyInjector(),
Build.VERSION.SDK_INT < 26 ? new AlarmManagerScheduler(application)
: new CompositeScheduler(new InAppScheduler(this), new JobSchedulerScheduler(application)),
new Debouncer(500),
@ -203,7 +203,6 @@ public class JobManager implements ConstraintObserver.Notifier {
private final List<ConstraintObserver> constraintObservers;
private final Data.Serializer dataSerializer;
private final JobStorage jobStorage;
private final DependencyInjector dependencyInjector;
private Configuration(int jobThreadCount,
@NonNull ExecutorFactory executorFactory,
@ -211,8 +210,7 @@ public class JobManager implements ConstraintObserver.Notifier {
@NonNull ConstraintInstantiator constraintInstantiator,
@NonNull List<ConstraintObserver> constraintObservers,
@NonNull Data.Serializer dataSerializer,
@NonNull JobStorage jobStorage,
@NonNull DependencyInjector dependencyInjector)
@NonNull JobStorage jobStorage)
{
this.executorFactory = executorFactory;
this.jobThreadCount = jobThreadCount;
@ -221,7 +219,6 @@ public class JobManager implements ConstraintObserver.Notifier {
this.constraintObservers = constraintObservers;
this.dataSerializer = dataSerializer;
this.jobStorage = jobStorage;
this.dependencyInjector = dependencyInjector;
}
int getJobThreadCount() {
@ -253,9 +250,6 @@ public class JobManager implements ConstraintObserver.Notifier {
return jobStorage;
}
@NonNull DependencyInjector getDependencyInjector() {
return dependencyInjector;
}
public static class Builder {
@ -266,7 +260,6 @@ public class JobManager implements ConstraintObserver.Notifier {
private List<ConstraintObserver> constraintObservers = new ArrayList<>();
private Data.Serializer dataSerializer = new JsonDataSerializer();
private JobStorage jobStorage = null;
private DependencyInjector dependencyInjector = o -> { /*noop*/ };
public @NonNull Builder setJobThreadCount(int jobThreadCount) {
this.jobThreadCount = jobThreadCount;
@ -303,11 +296,6 @@ public class JobManager implements ConstraintObserver.Notifier {
return this;
}
public @NonNull Builder setDependencyInjector(@NonNull DependencyInjector dependencyInjector) {
this.dependencyInjector = dependencyInjector;
return this;
}
public @NonNull Configuration build() {
return new Configuration(jobThreadCount,
executorFactory,
@ -315,8 +303,7 @@ public class JobManager implements ConstraintObserver.Notifier {
new ConstraintInstantiator(constraintFactories),
new ArrayList<>(constraintObservers),
dataSerializer,
jobStorage,
dependencyInjector);
jobStorage);
}
}
}

View File

@ -1,33 +1,33 @@
package org.thoughtcrime.securesms.jobs;
import android.graphics.Bitmap;
import androidx.annotation.NonNull;
import org.session.libsession.messaging.utilities.Data;
import org.session.libsession.utilities.DownloadUtilities;
import org.session.libsignal.streams.AttachmentCipherInputStream;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.session.libsession.utilities.GroupRecord;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.session.libsignal.exceptions.InvalidMessageException;
import org.session.libsignal.exceptions.NonSuccessfulResponseCodeException;
import org.session.libsignal.messages.SignalServiceAttachmentPointer;
import org.session.libsignal.streams.AttachmentCipherInputStream;
import org.session.libsignal.utilities.Hex;
import org.session.libsignal.utilities.Log;
import org.session.libsignal.utilities.guava.Optional;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.mms.AttachmentStreamUriLoader.AttachmentModel;
import org.thoughtcrime.securesms.util.BitmapDecodingException;
import org.thoughtcrime.securesms.util.BitmapUtil;
import org.session.libsignal.utilities.Hex;
import org.session.libsignal.exceptions.InvalidMessageException;
import org.session.libsignal.utilities.guava.Optional;
import org.session.libsignal.messages.SignalServiceAttachmentPointer;
import org.session.libsignal.exceptions.NonSuccessfulResponseCodeException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class AvatarDownloadJob extends BaseJob implements InjectableType {
public class AvatarDownloadJob extends BaseJob {
public static final String KEY = "AvatarDownloadJob";
@ -64,7 +64,7 @@ public class AvatarDownloadJob extends BaseJob implements InjectableType {
@Override
public void onRun() throws IOException {
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
GroupDatabase database = DatabaseComponent.get(context).groupDatabase();
Optional<GroupRecord> record = database.getGroup(groupId);
File attachment = null;

View File

@ -1,18 +1,18 @@
package org.thoughtcrime.securesms.jobs
import android.os.Build
import org.session.libsignal.utilities.Log
import org.greenrobot.eventbus.EventBus
import org.session.libsession.messaging.utilities.Data
import org.session.libsession.messaging.sending_receiving.attachments.Attachment
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachmentAudioExtras
import org.session.libsession.messaging.utilities.Data
import org.session.libsession.utilities.DecodedAudio
import org.session.libsession.utilities.InputStreamMediaDataSource
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.jobs.PrepareAttachmentAudioExtrasJob.AudioExtrasUpdatedEvent
import org.thoughtcrime.securesms.mms.PartAuthority
import java.lang.IllegalStateException
import java.util.*
import java.util.concurrent.TimeUnit
@ -68,7 +68,7 @@ class PrepareAttachmentAudioExtrasJob : BaseJob {
override fun onRun() {
Log.v(TAG, "Processing attachment: $attachmentId")
val attachDb = DatabaseFactory.getAttachmentDatabase(context)
val attachDb = DatabaseComponent.get(context).attachmentDatabase()
val attachment = attachDb.getAttachment(attachmentId)
if (attachment == null) {

View File

@ -8,16 +8,15 @@ import androidx.annotation.NonNull;
import org.session.libsession.avatars.AvatarHelper;
import org.session.libsession.messaging.utilities.Data;
import org.session.libsession.utilities.Address;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsession.utilities.DownloadUtilities;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.Util;
import org.session.libsignal.streams.ProfileCipherInputStream;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsignal.exceptions.PushNetworkException;
import org.session.libsignal.streams.ProfileCipherInputStream;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
@ -29,7 +28,7 @@ import java.io.InputStream;
import java.security.SecureRandom;
import java.util.concurrent.TimeUnit;
public class RetrieveProfileAvatarJob extends BaseJob implements InjectableType {
public class RetrieveProfileAvatarJob extends BaseJob {
public static final String KEY = "RetrieveProfileAvatarJob";
@ -77,7 +76,7 @@ public class RetrieveProfileAvatarJob extends BaseJob implements InjectableType
@Override
public void onRun() throws IOException {
RecipientDatabase database = DatabaseFactory.getRecipientDatabase(context);
RecipientDatabase database = DatabaseComponent.get(context).recipientDatabase();
byte[] profileKey = recipient.resolve().getProfileKey();
if (profileKey == null) {

View File

@ -19,11 +19,10 @@ package org.thoughtcrime.securesms.jobs;
import androidx.annotation.NonNull;
import org.session.libsession.messaging.utilities.Data;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.session.libsignal.utilities.Log;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.jobmanager.Job;
public class TrimThreadJob extends BaseJob {
@ -63,7 +62,7 @@ public class TrimThreadJob extends BaseJob {
if (!trimmingEnabled)
return;
DatabaseFactory.getThreadDatabase(context).trimThread(threadId, threadLengthLimit);
DatabaseComponent.get(context).threadDatabase().trimThread(threadId, threadLengthLimit);
}
@Override

View File

@ -4,42 +4,38 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.util.IOUtils;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress;
import org.session.libsession.messaging.sending_receiving.attachments.UriAttachment;
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview;
import org.session.libsession.utilities.MediaTypes;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.session.libsession.utilities.concurrent.SignalExecutors;
import org.session.libsignal.utilities.Log;
import org.session.libsignal.utilities.guava.Optional;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil.OpenGraph;
import org.thoughtcrime.securesms.net.CallRequestController;
import org.thoughtcrime.securesms.net.CompositeRequestController;
import org.thoughtcrime.securesms.net.ContentProxySafetyInterceptor;
import org.thoughtcrime.securesms.net.RequestController;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.session.libsignal.utilities.guava.Optional;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil.OpenGraph;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.session.libsession.messaging.sending_receiving.attachments.UriAttachment;
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview;
import org.session.libsession.utilities.concurrent.SignalExecutors;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.inject.Inject;
import okhttp3.CacheControl;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class LinkPreviewRepository implements InjectableType {
public class LinkPreviewRepository {
private static final String TAG = LinkPreviewRepository.class.getSimpleName();
@ -52,8 +48,6 @@ public class LinkPreviewRepository implements InjectableType {
.addNetworkInterceptor(new ContentProxySafetyInterceptor())
.cache(null)
.build();
ApplicationContext.getInstance(context).injectDependencies(this);
}
RequestController getLinkPreview(@NonNull Context context, @NonNull String url, @NonNull Callback<Optional<LinkPreview>> callback) {

View File

@ -123,7 +123,7 @@ class LogFile {
return builder.toString();
}
private String readEntry() throws IOException {
String readEntry() throws IOException {
try {
Util.readFully(inputStream, ivBuffer);
Util.readFully(inputStream, intBuffer);

View File

@ -0,0 +1,250 @@
package org.thoughtcrime.securesms.logging;
import android.content.Context;
import androidx.annotation.AnyThread;
import androidx.annotation.WorkerThread;
import org.session.libsignal.utilities.ListenableFuture;
import org.session.libsignal.utilities.Log;
import org.session.libsignal.utilities.NoExternalStorageException;
import org.session.libsignal.utilities.SettableFuture;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class PersistentLogger extends Log.Logger {
private static final String TAG = PersistentLogger.class.getSimpleName();
private static final String LOG_V = "V";
private static final String LOG_D = "D";
private static final String LOG_I = "I";
private static final String LOG_W = "W";
private static final String LOG_E = "E";
private static final String LOG_WTF = "A";
private static final String LOG_DIRECTORY = "log";
private static final String FILENAME_PREFIX = "log-";
private static final int MAX_LOG_FILES = 5;
private static final int MAX_LOG_SIZE = 300 * 1024;
private static final int MAX_LOG_EXPORT = 10_000;
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS zzz");
private final Context context;
private final Executor executor;
private final byte[] secret;
private LogFile.Writer writer;
public PersistentLogger(Context context) {
this.context = context.getApplicationContext();
this.secret = LogSecretProvider.getOrCreateAttachmentSecret(context);
this.executor = Executors.newSingleThreadExecutor(r -> {
Thread thread = new Thread(r, "PersistentLogger");
thread.setPriority(Thread.MIN_PRIORITY);
return thread;
});
executor.execute(this::initializeWriter);
}
@Override
public void v(String tag, String message, Throwable t) {
write(LOG_V, tag, message, t);
}
@Override
public void d(String tag, String message, Throwable t) {
write(LOG_D, tag, message, t);
}
@Override
public void i(String tag, String message, Throwable t) {
write(LOG_I, tag, message, t);
}
@Override
public void w(String tag, String message, Throwable t) {
write(LOG_W, tag, message, t);
}
@Override
public void e(String tag, String message, Throwable t) {
write(LOG_E, tag, message, t);
}
@Override
public void wtf(String tag, String message, Throwable t) {
write(LOG_WTF, tag, message, t);
}
@Override
public void blockUntilAllWritesFinished() {
CountDownLatch latch = new CountDownLatch(1);
executor.execute(latch::countDown);
try {
latch.await();
} catch (InterruptedException e) {
android.util.Log.w(TAG, "Failed to wait for all writes.");
}
}
@WorkerThread
public ListenableFuture<String> getLogs() {
final SettableFuture<String> future = new SettableFuture<>();
executor.execute(() -> {
StringBuilder builder = new StringBuilder();
long entriesWritten = 0;
try {
File[] logs = getSortedLogFiles();
for (int i = logs.length - 1; i >= 0 && entriesWritten <= MAX_LOG_EXPORT; i--) {
try {
LogFile.Reader reader = new LogFile.Reader(secret, logs[i]);
String entry;
while ((entry = reader.readEntry()) != null) {
entriesWritten++;
builder.append(entry).append('\n');
}
} catch (IOException e) {
android.util.Log.w(TAG, "Failed to read log at index " + i + ". Removing reference.");
logs[i].delete();
}
}
future.set(builder.toString());
} catch (NoExternalStorageException e) {
future.setException(e);
}
});
return future;
}
@WorkerThread
private void initializeWriter() {
try {
writer = new LogFile.Writer(secret, getOrCreateActiveLogFile());
} catch (NoExternalStorageException | IOException e) {
android.util.Log.e(TAG, "Failed to initialize writer.", e);
}
}
@AnyThread
private void write(String level, String tag, String message, Throwable t) {
executor.execute(() -> {
try {
if (writer == null) {
return;
}
if (writer.getLogSize() >= MAX_LOG_SIZE) {
writer.close();
writer = new LogFile.Writer(secret, createNewLogFile());
trimLogFilesOverMax();
}
for (String entry : buildLogEntries(level, tag, message, t)) {
writer.writeEntry(entry);
}
} catch (NoExternalStorageException e) {
android.util.Log.w(TAG, "Cannot persist logs.", e);
} catch (IOException e) {
android.util.Log.w(TAG, "Failed to write line. Deleting all logs and starting over.");
deleteAllLogs();
initializeWriter();
}
});
}
private void trimLogFilesOverMax() throws NoExternalStorageException {
File[] logs = getSortedLogFiles();
if (logs.length > MAX_LOG_FILES) {
for (int i = MAX_LOG_FILES; i < logs.length; i++) {
logs[i].delete();
}
}
}
private void deleteAllLogs() {
try {
File[] logs = getSortedLogFiles();
for (File log : logs) {
log.delete();
}
} catch (NoExternalStorageException e) {
android.util.Log.w(TAG, "Was unable to delete logs.", e);
}
}
private File getOrCreateActiveLogFile() throws NoExternalStorageException {
File[] logs = getSortedLogFiles();
if (logs.length > 0) {
return logs[0];
}
return createNewLogFile();
}
private File createNewLogFile() throws NoExternalStorageException {
return new File(getOrCreateLogDirectory(), FILENAME_PREFIX + System.currentTimeMillis());
}
private File[] getSortedLogFiles() throws NoExternalStorageException {
File[] logs = getOrCreateLogDirectory().listFiles();
if (logs != null) {
Arrays.sort(logs, (o1, o2) -> o2.getName().compareTo(o1.getName()));
return logs;
}
return new File[0];
}
private File getOrCreateLogDirectory() throws NoExternalStorageException {
File logDir = new File(context.getCacheDir(), LOG_DIRECTORY);
if (!logDir.exists() && !logDir.mkdir()) {
throw new NoExternalStorageException("Unable to create log directory.");
}
return logDir;
}
private List<String> buildLogEntries(String level, String tag, String message, Throwable t) {
List<String> entries = new LinkedList<>();
Date date = new Date();
entries.add(buildEntry(level, tag, message, date));
if (t != null) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
t.printStackTrace(new PrintStream(outputStream));
String trace = new String(outputStream.toByteArray());
String[] lines = trace.split("\\n");
for (String line : lines) {
entries.add(buildEntry(level, tag, line, date));
}
}
return entries;
}
private String buildEntry(String level, String tag, String message, Date date) {
return DATE_FORMAT.format(date) + ' ' + level + ' ' + tag + ": " + message;
}
}

View File

@ -3,20 +3,21 @@ package org.thoughtcrime.securesms.longmessage;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.session.libsession.utilities.Util;
import org.session.libsession.utilities.concurrent.SignalExecutors;
import org.session.libsignal.utilities.Log;
import org.session.libsignal.utilities.guava.Optional;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.mms.TextSlide;
import org.session.libsession.utilities.Util;
import org.session.libsession.utilities.concurrent.SignalExecutors;
import org.session.libsignal.utilities.guava.Optional;
import java.io.IOException;
import java.io.InputStream;
@ -29,8 +30,8 @@ class LongMessageRepository {
private final SmsDatabase smsDatabase;
LongMessageRepository(@NonNull Context context) {
this.mmsDatabase = DatabaseFactory.getMmsDatabase(context);
this.smsDatabase = DatabaseFactory.getSmsDatabase(context);
this.mmsDatabase = DatabaseComponent.get(context).mmsDatabase();
this.smsDatabase = DatabaseComponent.get(context).smsDatabase();
}
void getMessage(@NonNull Context context, long messageId, boolean isMms, @NonNull Callback<Optional<LongMessage>> callback) {

View File

@ -4,12 +4,13 @@ import android.content.ContentUris;
import android.content.Context;
import android.content.UriMatcher;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.providers.PartProvider;
@ -47,8 +48,8 @@ public class PartAuthority {
int match = uriMatcher.match(uri);
try {
switch (match) {
case PART_ROW: return DatabaseFactory.getAttachmentDatabase(context).getAttachmentStream(new PartUriParser(uri).getPartId(), 0);
case THUMB_ROW: return DatabaseFactory.getAttachmentDatabase(context).getThumbnailStream(new PartUriParser(uri).getPartId());
case PART_ROW: return DatabaseComponent.get(context).attachmentDatabase().getAttachmentStream(new PartUriParser(uri).getPartId(), 0);
case THUMB_ROW: return DatabaseComponent.get(context).attachmentDatabase().getThumbnailStream(new PartUriParser(uri).getPartId());
case BLOB_ROW: return BlobProvider.getInstance().getStream(context, uri);
default: return context.getContentResolver().openInputStream(uri);
}
@ -63,7 +64,7 @@ public class PartAuthority {
switch (match) {
case THUMB_ROW:
case PART_ROW:
Attachment attachment = DatabaseFactory.getAttachmentDatabase(context).getAttachment(new PartUriParser(uri).getPartId());
Attachment attachment = DatabaseComponent.get(context).attachmentDatabase().getAttachment(new PartUriParser(uri).getPartId());
if (attachment != null) return attachment.getFileName();
else return null;
@ -80,7 +81,7 @@ public class PartAuthority {
switch (match) {
case THUMB_ROW:
case PART_ROW:
Attachment attachment = DatabaseFactory.getAttachmentDatabase(context).getAttachment(new PartUriParser(uri).getPartId());
Attachment attachment = DatabaseComponent.get(context).attachmentDatabase().getAttachment(new PartUriParser(uri).getPartId());
if (attachment != null) return attachment.getSize();
else return null;
@ -97,7 +98,7 @@ public class PartAuthority {
switch (match) {
case THUMB_ROW:
case PART_ROW:
Attachment attachment = DatabaseFactory.getAttachmentDatabase(context).getAttachment(new PartUriParser(uri).getPartId());
Attachment attachment = DatabaseComponent.get(context).attachmentDatabase().getAttachment(new PartUriParser(uri).getPartId());
if (attachment != null) return attachment.getContentType();
else return null;

View File

@ -22,12 +22,13 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import androidx.core.app.NotificationManagerCompat;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import java.util.LinkedList;
import java.util.List;
@ -62,7 +63,7 @@ public class AndroidAutoHeardReceiver extends BroadcastReceiver {
for (long threadId : threadIds) {
Log.i(TAG, "Marking meassage as read: " + threadId);
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(threadId, true);
List<MarkedMessageInfo> messageIds = DatabaseComponent.get(context).threadDatabase().setRead(threadId, true);
messageIdsCollection.addAll(messageIds);
}

View File

@ -23,19 +23,20 @@ import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import androidx.core.app.RemoteInput;
import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage;
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
import org.session.libsession.messaging.messages.visible.VisibleMessage;
import org.session.libsession.messaging.sending_receiving.MessageSender;
import org.thoughtcrime.securesms.ApplicationContext;
import org.session.libsession.utilities.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.thoughtcrime.securesms.mms.MmsException;
import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.mms.MmsException;
import java.util.Collections;
import java.util.List;
@ -74,7 +75,7 @@ public class AndroidAutoReplyReceiver extends BroadcastReceiver {
long replyThreadId;
if (threadId == -1) {
replyThreadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
replyThreadId = DatabaseComponent.get(context).threadDatabase().getOrCreateThreadIdFor(recipient);
} else {
replyThreadId = threadId;
}
@ -88,17 +89,17 @@ public class AndroidAutoReplyReceiver extends BroadcastReceiver {
Log.w("AndroidAutoReplyReceiver", "GroupRecipient, Sending media message");
OutgoingMediaMessage reply = OutgoingMediaMessage.from(message, recipient, Collections.emptyList(), null, null);
try {
DatabaseFactory.getMmsDatabase(context).insertMessageOutbox(reply, replyThreadId, false, null);
DatabaseComponent.get(context).mmsDatabase().insertMessageOutbox(reply, replyThreadId, false, null);
} catch (MmsException e) {
Log.w(TAG, e);
}
} else {
Log.w("AndroidAutoReplyReceiver", "Sending regular message ");
OutgoingTextMessage reply = OutgoingTextMessage.from(message, recipient);
DatabaseFactory.getSmsDatabase(context).insertMessageOutbox(replyThreadId, reply, false, System.currentTimeMillis(), null);
DatabaseComponent.get(context).smsDatabase().insertMessageOutbox(replyThreadId, reply, false, System.currentTimeMillis(), null);
}
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(replyThreadId, true);
List<MarkedMessageInfo> messageIds = DatabaseComponent.get(context).threadDatabase().setRead(replyThreadId, true);
ApplicationContext.getInstance(context).messageNotifier.updateNotification(context);
MarkReadReceiver.process(context, messageIds);

View File

@ -14,7 +14,7 @@ import org.session.libsession.messaging.sending_receiving.pollers.OpenGroupPolle
import org.session.libsession.snode.SnodeAPI
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import java.util.concurrent.TimeUnit
class BackgroundPollWorker(val context: Context, params: WorkerParameters) : Worker(context, params) {
@ -63,7 +63,7 @@ class BackgroundPollWorker(val context: Context, params: WorkerParameters) : Wor
allGroupPublicKeys.forEach { closedGroupPoller.poll(it) }
// Open Groups
val threadDB = DatabaseFactory.getLokiThreadDatabase(context)
val threadDB = DatabaseComponent.get(context).lokiThreadDatabase()
val v2OpenGroups = threadDB.getAllV2OpenGroups()
val v2OpenGroupServers = v2OpenGroups.map { it.value.server }.toSet()

View File

@ -52,7 +52,6 @@ import org.thoughtcrime.securesms.contactshare.ContactUtil;
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2;
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities;
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
import org.thoughtcrime.securesms.database.RecipientDatabase;
@ -61,6 +60,7 @@ import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.database.model.Quote;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.SessionMetaProtocol;
@ -97,7 +97,7 @@ public class DefaultMessageNotifier implements MessageNotifier {
private static final int SUMMARY_NOTIFICATION_ID = 1338;
private static final int PENDING_MESSAGES_ID = 1111;
private static final String NOTIFICATION_GROUP = "messages";
private static final long MIN_AUDIBLE_PERIOD_MILLIS = TimeUnit.SECONDS.toMillis(2);
private static final long MIN_AUDIBLE_PERIOD_MILLIS = TimeUnit.SECONDS.toMillis(5);
private static final long DESKTOP_ACTIVITY_PERIOD = TimeUnit.MINUTES.toMillis(1);
private volatile static long visibleThread = -1;
@ -228,9 +228,8 @@ public class DefaultMessageNotifier implements MessageNotifier {
{
boolean isVisible = visibleThread == threadId;
ThreadDatabase threads = DatabaseFactory.getThreadDatabase(context);
Recipient recipients = DatabaseFactory.getThreadDatabase(context)
.getRecipientForThreadId(threadId);
ThreadDatabase threads = DatabaseComponent.get(context).threadDatabase();
Recipient recipients = threads.getRecipientForThreadId(threadId);
if (isVisible && recipients != null) {
List<MarkedMessageInfo> messageIds = threads.setRead(threadId, false);
@ -257,8 +256,8 @@ public class DefaultMessageNotifier implements MessageNotifier {
Cursor pushCursor = null;
try {
telcoCursor = DatabaseFactory.getMmsSmsDatabase(context).getUnread();
pushCursor = DatabaseFactory.getPushDatabase(context).getPending();
telcoCursor = DatabaseComponent.get(context).mmsSmsDatabase().getUnread();
pushCursor = DatabaseComponent.get(context).pushDatabase().getPending();
if (((telcoCursor == null || telcoCursor.isAfterLast()) &&
(pushCursor == null || pushCursor.isAfterLast())) || !TextSecurePreferences.hasSeenWelcomeScreen(context))
@ -440,9 +439,12 @@ public class DefaultMessageNotifier implements MessageNotifier {
private void sendInThreadNotification(Context context, Recipient recipient) {
if (!TextSecurePreferences.isInThreadNotifications(context) ||
ServiceUtil.getAudioManager(context).getRingerMode() != AudioManager.RINGER_MODE_NORMAL)
ServiceUtil.getAudioManager(context).getRingerMode() != AudioManager.RINGER_MODE_NORMAL ||
(System.currentTimeMillis() - lastAudibleNotification) < MIN_AUDIBLE_PERIOD_MILLIS)
{
return;
} else {
lastAudibleNotification = System.currentTimeMillis();
}
Uri uri = null;
@ -481,7 +483,7 @@ public class DefaultMessageNotifier implements MessageNotifier {
@NonNull Cursor cursor)
{
NotificationState notificationState = new NotificationState();
MmsSmsDatabase.Reader reader = DatabaseFactory.getMmsSmsDatabase(context).readerFor(cursor);
MmsSmsDatabase.Reader reader = DatabaseComponent.get(context).mmsSmsDatabase().readerFor(cursor);
MessageRecord record;
@ -498,7 +500,7 @@ public class DefaultMessageNotifier implements MessageNotifier {
if (threadId != -1) {
threadRecipients = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
threadRecipients = DatabaseComponent.get(context).threadDatabase().getRecipientForThreadId(threadId);
}
if (KeyCachingService.isLocked(context)) {

View File

@ -7,7 +7,7 @@ import android.content.Intent;
import android.os.AsyncTask;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
public class DeleteNotificationReceiver extends BroadcastReceiver {
@ -30,8 +30,8 @@ public class DeleteNotificationReceiver extends BroadcastReceiver {
@Override
protected Void doInBackground(Void... params) {
for (int i=0;i<ids.length;i++) {
if (!mms[i]) DatabaseFactory.getSmsDatabase(context).markAsNotified(ids[i]);
else DatabaseFactory.getMmsDatabase(context).markAsNotified(ids[i]);
if (!mms[i]) DatabaseComponent.get(context).smsDatabase().markAsNotified(ids[i]);
else DatabaseComponent.get(context).mmsDatabase().markAsNotified(ids[i]);
}
return null;

View File

@ -2,14 +2,16 @@ package org.thoughtcrime.securesms.notifications
import android.content.Context
import nl.komponents.kovenant.functional.map
import okhttp3.*
import okhttp3.MediaType
import okhttp3.Request
import okhttp3.RequestBody
import org.session.libsession.messaging.sending_receiving.notifications.PushNotificationAPI
import org.session.libsession.snode.OnionRequestAPI
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsignal.utilities.Log
import org.session.libsignal.utilities.JsonUtil
import org.session.libsignal.utilities.Log
import org.session.libsignal.utilities.retryIfNeeded
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
object LokiPushNotificationManager {
private val maxRetryCount = 4
@ -53,7 +55,7 @@ object LokiPushNotificationManager {
}
}
// Unsubscribe from all closed groups
val allClosedGroupPublicKeys = DatabaseFactory.getLokiAPIDatabase(context).getAllClosedGroupPublicKeys()
val allClosedGroupPublicKeys = DatabaseComponent.get(context).lokiAPIDatabase().getAllClosedGroupPublicKeys()
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
allClosedGroupPublicKeys.forEach { closedGroup ->
performOperation(context, ClosedGroupOperation.Unsubscribe, closedGroup, userPublicKey)
@ -84,7 +86,7 @@ object LokiPushNotificationManager {
}
}
// Subscribe to all closed groups
val allClosedGroupPublicKeys = DatabaseFactory.getLokiAPIDatabase(context).getAllClosedGroupPublicKeys()
val allClosedGroupPublicKeys = DatabaseComponent.get(context).lokiAPIDatabase().getAllClosedGroupPublicKeys()
allClosedGroupPublicKeys.forEach { closedGroup ->
performOperation(context, ClosedGroupOperation.Subscribe, closedGroup, publicKey)
}

View File

@ -5,6 +5,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationManagerCompat;
@ -13,16 +14,16 @@ import com.annimon.stream.Stream;
import org.session.libsession.messaging.messages.control.ReadReceipt;
import org.session.libsession.messaging.sending_receiving.MessageSender;
import org.session.libsession.utilities.TextSecurePreferences;
import org.thoughtcrime.securesms.ApplicationContext;
import org.session.libsession.utilities.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.database.MessagingDatabase.ExpirationInfo;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.util.SessionMetaProtocol;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.thoughtcrime.securesms.util.SessionMetaProtocol;
import java.util.LinkedList;
import java.util.List;
@ -53,7 +54,7 @@ public class MarkReadReceiver extends BroadcastReceiver {
for (long threadId : threadIds) {
Log.i(TAG, "Marking as read: " + threadId);
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(threadId, true);
List<MarkedMessageInfo> messageIds = DatabaseComponent.get(context).threadDatabase().setRead(threadId, true);
messageIdsCollection.addAll(messageIds);
}
@ -92,8 +93,8 @@ public class MarkReadReceiver extends BroadcastReceiver {
if (expirationInfo.getExpiresIn() > 0 && expirationInfo.getExpireStarted() <= 0) {
ExpiringMessageManager expirationManager = ApplicationContext.getInstance(context).getExpiringMessageManager();
if (expirationInfo.isMms()) DatabaseFactory.getMmsDatabase(context).markExpireStarted(expirationInfo.getId());
else DatabaseFactory.getSmsDatabase(context).markExpireStarted(expirationInfo.getId());
if (expirationInfo.isMms()) DatabaseComponent.get(context).mmsDatabase().markExpireStarted(expirationInfo.getId());
else DatabaseComponent.get(context).smsDatabase().markExpireStarted(expirationInfo.getId());
expirationManager.scheduleDeletion(expirationInfo.getId(), expirationInfo.isMms(), expirationInfo.getExpiresIn());
}

View File

@ -15,8 +15,8 @@ import org.session.libsession.utilities.NotificationPrivacyPreference;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.Util;
import org.session.libsession.utilities.recipients.Recipient;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.SessionContactDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.home.HomeActivity;
import java.util.LinkedList;
@ -116,7 +116,7 @@ public class MultipleRecipientNotificationBuilder extends AbstractNotificationBu
* @param recipient the * individual * recipient for which to get the open group display name.
*/
private String getOpenGroupDisplayName(Recipient recipient) {
SessionContactDatabase contactDB = DatabaseFactory.getSessionContactDatabase(context);
SessionContactDatabase contactDB = DatabaseComponent.get(context).sessionContactDatabase();
String sessionID = recipient.getAddress().serialize();
Contact contact = contactDB.getContactWithSessionID(sessionID);
if (contact == null) { return sessionID; }

View File

@ -12,24 +12,23 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.provider.Settings;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import android.text.TextUtils;
import com.annimon.stream.Collectors;
import com.annimon.stream.Stream;
import network.loki.messenger.BuildConfig;
import network.loki.messenger.R;
import org.session.libsession.utilities.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsession.utilities.recipients.Recipient.*;
import org.session.libsession.utilities.ServiceUtil;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsession.utilities.recipients.Recipient.VibrateState;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import java.util.ArrayList;
import java.util.Arrays;
@ -37,6 +36,9 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import network.loki.messenger.BuildConfig;
import network.loki.messenger.R;
public class NotificationChannels {
private static final String TAG = NotificationChannels.class.getSimpleName();
@ -90,7 +92,7 @@ public class NotificationChannels {
return;
}
RecipientDatabase db = DatabaseFactory.getRecipientDatabase(context);
RecipientDatabase db = DatabaseComponent.get(context).recipientDatabase();
try (RecipientDatabase.RecipientReader reader = db.getRecipientsWithNotificationChannels()) {
Recipient recipient;
@ -292,7 +294,7 @@ public class NotificationChannels {
generateChannelIdFor(recipient.getAddress()),
channel -> channel.setSound(uri == null ? Settings.System.DEFAULT_NOTIFICATION_URI : uri, getRingtoneAudioAttributes()));
DatabaseFactory.getRecipientDatabase(context).setNotificationChannel(recipient, success ? newChannelId : null);
DatabaseComponent.get(context).recipientDatabase().setNotificationChannel(recipient, success ? newChannelId : null);
ensureCustomChannelConsistency(context);
}
@ -359,7 +361,7 @@ public class NotificationChannels {
newChannelId,
channel -> channel.enableVibration(enabled));
DatabaseFactory.getRecipientDatabase(context).setNotificationChannel(recipient, success ? newChannelId : null);
DatabaseComponent.get(context).recipientDatabase().setNotificationChannel(recipient, success ? newChannelId : null);
ensureCustomChannelConsistency(context);
}
@ -391,7 +393,7 @@ public class NotificationChannels {
@WorkerThread
public static synchronized void ensureCustomChannelConsistency(@NonNull Context context) {
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
RecipientDatabase db = DatabaseFactory.getRecipientDatabase(context);
RecipientDatabase db = DatabaseComponent.get(context).recipientDatabase();
List<Recipient> customRecipients = new ArrayList<>();
Set<String> customChannelIds = new HashSet<>();
Set<String> existingChannelIds = Stream.of(notificationManager.getNotificationChannels()).map(NotificationChannel::getId).collect(Collectors.toSet());
@ -503,7 +505,7 @@ public class NotificationChannels {
@WorkerThread
@TargetApi(26)
private static void updateAllRecipientChannelLedColors(@NonNull Context context, @NonNull NotificationManager notificationManager, @NonNull String color) {
RecipientDatabase database = DatabaseFactory.getRecipientDatabase(context);
RecipientDatabase database = DatabaseComponent.get(context).recipientDatabase();
try (RecipientDatabase.RecipientReader recipients = database.getRecipientsWithNotificationChannels()) {
Recipient recipient;

View File

@ -23,19 +23,21 @@ import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import androidx.core.app.RemoteInput;
import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage;
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage;
import org.session.libsession.messaging.messages.visible.VisibleMessage;
import org.session.libsession.messaging.sending_receiving.MessageSender;
import org.session.libsession.utilities.Address;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.session.libsession.utilities.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.mms.MmsException;
import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage;
import org.session.libsession.utilities.recipients.Recipient;
import java.util.Collections;
import java.util.List;
@ -71,7 +73,8 @@ public class RemoteReplyReceiver extends BroadcastReceiver {
@Override
protected Void doInBackground(Void... params) {
Recipient recipient = Recipient.from(context, address, false);
long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
ThreadDatabase threadDatabase = DatabaseComponent.get(context).threadDatabase();
long threadId = threadDatabase.getOrCreateThreadIdFor(recipient);
VisibleMessage message = new VisibleMessage();
message.setSentTimestamp(System.currentTimeMillis());
message.setText(responseText.toString());
@ -80,7 +83,7 @@ public class RemoteReplyReceiver extends BroadcastReceiver {
case GroupMessage: {
OutgoingMediaMessage reply = OutgoingMediaMessage.from(message, recipient, Collections.emptyList(), null, null);
try {
DatabaseFactory.getMmsDatabase(context).insertMessageOutbox(reply, threadId, false, null);
DatabaseComponent.get(context).mmsDatabase().insertMessageOutbox(reply, threadId, false, null);
MessageSender.send(message, address);
} catch (MmsException e) {
Log.w(TAG, e);
@ -89,7 +92,7 @@ public class RemoteReplyReceiver extends BroadcastReceiver {
}
case SecureMessage: {
OutgoingTextMessage reply = OutgoingTextMessage.from(message, recipient);
DatabaseFactory.getSmsDatabase(context).insertMessageOutbox(threadId, reply, false, System.currentTimeMillis(), null);
DatabaseComponent.get(context).smsDatabase().insertMessageOutbox(threadId, reply, false, System.currentTimeMillis(), null);
MessageSender.send(message, address);
break;
}
@ -97,7 +100,7 @@ public class RemoteReplyReceiver extends BroadcastReceiver {
throw new AssertionError("Unknown Reply method");
}
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(threadId, true);
List<MarkedMessageInfo> messageIds = threadDatabase.setRead(threadId, true);
ApplicationContext.getInstance(context).messageNotifier.updateNotification(context);
MarkReadReceiver.process(context, messageIds);

View File

@ -34,8 +34,8 @@ import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.Util;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.SessionContactDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.Slide;
@ -337,7 +337,7 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
* @param recipient the * individual * recipient for which to get the open group display name.
*/
private String getOpenGroupDisplayName(Recipient recipient) {
SessionContactDatabase contactDB = DatabaseFactory.getSessionContactDatabase(context);
SessionContactDatabase contactDB = DatabaseComponent.get(context).sessionContactDatabase();
String sessionID = recipient.getAddress().serialize();
Contact contact = contactDB.getContactWithSessionID(sessionID);
if (contact == null) { return sessionID; }

View File

@ -7,26 +7,23 @@ import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;
import org.session.libsession.utilities.TextSecurePreferences;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.session.libsession.utilities.TextSecurePreferences;
import java.util.concurrent.TimeUnit;
import mobi.upod.timedurationpicker.TimeDurationPickerDialog;
import network.loki.messenger.R;
public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment implements InjectableType {
public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment {
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
ApplicationContext.getInstance(activity).injectDependencies(this);
}
@Override

View File

@ -13,19 +13,14 @@ import androidx.fragment.app.FragmentPagerAdapter
import kotlinx.android.synthetic.main.activity_qr_code.*
import kotlinx.android.synthetic.main.fragment_view_my_qr_code.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.session.libsession.utilities.Address
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.util.ScanQRCodeWrapperFragment
import org.thoughtcrime.securesms.util.ScanQRCodeWrapperFragmentDelegate
import org.thoughtcrime.securesms.util.QRCodeUtilities
import org.thoughtcrime.securesms.util.toPx
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.util.FileProviderUtil
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsignal.utilities.PublicKeyValidation
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.util.*
import java.io.File
import java.io.FileOutputStream
@ -56,7 +51,7 @@ class QRCodeActivity : PassphraseRequiredActionBarActivity(), ScanQRCodeWrapperF
val intent = Intent(this, ConversationActivityV2::class.java)
intent.putExtra(ConversationActivityV2.ADDRESS, recipient.address)
intent.setDataAndType(getIntent().data, getIntent().type)
val existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient)
val existingThread = DatabaseComponent.get(this).threadDatabase().getThreadIdIfExistsFor(recipient)
intent.putExtra(ConversationActivityV2.THREAD_ID, existingThread)
startActivity(intent)
finish()

View File

@ -85,6 +85,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
helpTranslateButton.setOnClickListener { helpTranslate() }
seedButton.setOnClickListener { showSeed() }
clearAllDataButton.setOnClickListener { clearAllData() }
supportButton.setOnClickListener { shareLogs() }
val isLightMode = UiModeUtilities.isDayUiMode(this)
oxenLogoImageView.setImageResource(if (isLightMode) R.drawable.oxen_light_mode else R.drawable.oxen_dark_mode)
versionTextView.text = String.format(getString(R.string.version_s), "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})")
@ -321,6 +322,10 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
ClearAllDataDialog().show(supportFragmentManager, "Clear All Data Dialog")
}
private fun shareLogs() {
ShareLogsDialog().show(supportFragmentManager,"Share Logs Dialog")
}
// endregion
private inner class DisplayNameEditActionModeCallback: ActionMode.Callback {

View File

@ -0,0 +1,65 @@
package org.thoughtcrime.securesms.preferences
import android.content.Intent
import android.os.Build
import android.view.LayoutInflater
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.lifecycleScope
import kotlinx.android.synthetic.main.dialog_share_logs.view.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import network.loki.messenger.BuildConfig
import network.loki.messenger.R
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
import org.thoughtcrime.securesms.providers.BlobProvider
class ShareLogsDialog : BaseDialog() {
private var shareJob: Job? = null
override fun setContentView(builder: AlertDialog.Builder) {
val contentView =
LayoutInflater.from(requireContext()).inflate(R.layout.dialog_share_logs, null)
contentView.cancelButton.setOnClickListener {
dismiss()
}
contentView.shareButton.setOnClickListener {
// start the export and share
shareLogs()
}
builder.setView(contentView)
builder.setCancelable(false)
}
private fun shareLogs() {
shareJob?.cancel()
shareJob = lifecycleScope.launch(Dispatchers.IO) {
val persistentLogger = ApplicationContext.getInstance(context).persistentLogger
try {
val logs = persistentLogger.logs.get()
val fileName = "${Build.MANUFACTURER}-${Build.DEVICE}-API${Build.VERSION.SDK_INT}-v${BuildConfig.VERSION_NAME}.log"
val logUri = BlobProvider().forData(logs.toByteArray())
.withFileName(fileName)
.withMimeType("text/plain")
.createForSingleSessionOnDisk(requireContext(),null)
val shareIntent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_STREAM, logUri)
type = "text/plain"
}
dismiss()
startActivity(Intent.createChooser(shareIntent, getString(R.string.share)))
} catch (e: Exception) {
Toast.makeText(context,"Error saving logs", Toast.LENGTH_LONG).show()
dismiss()
}
}
}
}

View File

@ -26,15 +26,14 @@ import android.net.Uri;
import android.os.MemoryFile;
import android.os.ParcelFileDescriptor;
import android.provider.OpenableColumns;
import androidx.annotation.NonNull;
import org.session.libsignal.utilities.Log;
import androidx.annotation.NonNull;
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId;
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment;
import org.session.libsession.utilities.Util;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.mms.PartUriParser;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.MemoryFileUtil;
@ -107,7 +106,7 @@ public class PartProvider extends ContentProvider {
switch (uriMatcher.match(uri)) {
case SINGLE_ROW:
PartUriParser partUriParser = new PartUriParser(uri);
DatabaseAttachment attachment = DatabaseFactory.getAttachmentDatabase(getContext())
DatabaseAttachment attachment = DatabaseComponent.get(getContext()).attachmentDatabase()
.getAttachment(partUriParser.getPartId());
if (attachment != null) {
@ -133,7 +132,7 @@ public class PartProvider extends ContentProvider {
switch (uriMatcher.match(url)) {
case SINGLE_ROW:
PartUriParser partUri = new PartUriParser(url);
DatabaseAttachment attachment = DatabaseFactory.getAttachmentDatabase(getContext()).getAttachment(partUri.getPartId());
DatabaseAttachment attachment = DatabaseComponent.get(getContext()).attachmentDatabase().getAttachment(partUri.getPartId());
if (attachment == null) return null;
@ -160,10 +159,10 @@ public class PartProvider extends ContentProvider {
}
private ParcelFileDescriptor getParcelStreamForAttachment(AttachmentId attachmentId) throws IOException {
long plaintextLength = Util.getStreamLength(DatabaseFactory.getAttachmentDatabase(getContext()).getAttachmentStream(attachmentId, 0));
long plaintextLength = Util.getStreamLength(DatabaseComponent.get(getContext()).attachmentDatabase().getAttachmentStream(attachmentId, 0));
MemoryFile memoryFile = new MemoryFile(attachmentId.toString(), Util.toIntExact(plaintextLength));
InputStream in = DatabaseFactory.getAttachmentDatabase(getContext()).getAttachmentStream(attachmentId, 0);
InputStream in = DatabaseComponent.get(getContext()).attachmentDatabase().getAttachmentStream(attachmentId, 0);
OutputStream out = memoryFile.getOutputStream();
Util.copy(in, out);

View File

@ -11,16 +11,17 @@ import android.os.Bundle;
import android.os.Parcel;
import android.service.chooser.ChooserTarget;
import android.service.chooser.ChooserTargetService;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.ShareActivity;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.session.libsession.utilities.recipients.Recipient;
import org.thoughtcrime.securesms.util.BitmapUtil;
import java.util.LinkedList;
@ -38,7 +39,7 @@ public class DirectShareService extends ChooserTargetService {
{
List<ChooserTarget> results = new LinkedList<>();
ComponentName componentName = new ComponentName(this, ShareActivity.class);
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(this);
ThreadDatabase threadDatabase = DatabaseComponent.get(this).threadDatabase();
Cursor cursor = threadDatabase.getDirectShareList();
try {

View File

@ -2,24 +2,22 @@ package org.thoughtcrime.securesms.service;
import android.content.Context;
import org.jetbrains.annotations.NotNull;
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate;
import org.session.libsession.messaging.messages.signal.IncomingMediaMessage;
import org.session.libsession.messaging.messages.signal.OutgoingExpirationUpdateMessage;
import org.session.libsession.utilities.Address;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsession.utilities.GroupUtil;
import org.session.libsession.utilities.SSKEnvironment;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsignal.utilities.guava.Optional;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsignal.messages.SignalServiceGroup;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.session.libsignal.utilities.guava.Optional;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.session.libsession.messaging.messages.signal.IncomingMediaMessage;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.mms.MmsException;
import java.io.IOException;
@ -41,8 +39,8 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
public ExpiringMessageManager(Context context) {
this.context = context.getApplicationContext();
this.smsDatabase = DatabaseFactory.getSmsDatabase(context);
this.mmsDatabase = DatabaseFactory.getMmsDatabase(context);
this.smsDatabase = DatabaseComponent.get(context).smsDatabase();
this.mmsDatabase = DatabaseComponent.get(context).mmsDatabase();
executor.execute(new LoadTask());
executor.execute(new ProcessTask());
@ -81,12 +79,12 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
}
if (message.getId() != null) {
DatabaseFactory.getSmsDatabase(context).deleteMessage(message.getId());
DatabaseComponent.get(context).smsDatabase().deleteMessage(message.getId());
}
}
private void insertIncomingExpirationTimerMessage(ExpirationTimerUpdate message) {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
MmsDatabase database = DatabaseComponent.get(context).mmsDatabase();
String senderPublicKey = message.getSender();
Long sentTimestamp = message.getSentTimestamp();
@ -123,7 +121,7 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
database.insertSecureDecryptedMessageInbox(mediaMessage, -1);
//set the timer to the conversation
DatabaseFactory.getRecipientDatabase(context).setExpireMessages(recipient, duration);
DatabaseComponent.get(context).recipientDatabase().setExpireMessages(recipient, duration);
} catch (IOException | MmsException ioe) {
Log.e("Loki", "Failed to insert expiration update message.");
@ -131,7 +129,7 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
}
private void insertOutgoingExpirationTimerMessage(ExpirationTimerUpdate message) {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
MmsDatabase database = DatabaseComponent.get(context).mmsDatabase();
Long sentTimestamp = message.getSentTimestamp();
String groupId = message.getGroupPublicKey();
@ -149,7 +147,7 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
recipient = Recipient.from(context, Address.fromSerialized(GroupUtil.doubleEncodeGroupID(groupId)), false);
}
//set the timer to the conversation
DatabaseFactory.getRecipientDatabase(context).setExpireMessages(recipient, duration);
DatabaseComponent.get(context).recipientDatabase().setExpireMessages(recipient, duration);
} catch (MmsException | IOException ioe) {
Log.e("Loki", "Failed to insert expiration update message.");
@ -163,7 +161,7 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
@Override
public void startAnyExpiration(long timestamp, @NotNull String author) {
MessageRecord messageRecord = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(timestamp, author);
MessageRecord messageRecord = DatabaseComponent.get(context).mmsSmsDatabase().getMessageFor(timestamp, author);
if (messageRecord != null) {
boolean mms = messageRecord.isMms();
Recipient recipient = messageRecord.getRecipient();

View File

@ -2,20 +2,20 @@ package org.thoughtcrime.securesms.sskenvironment
import android.content.Context
import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsession.utilities.SSKEnvironment
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
class ProfileManager : SSKEnvironment.ProfileManagerProtocol {
override fun setNickname(context: Context, recipient: Recipient, nickname: String?) {
val sessionID = recipient.address.serialize()
val contactDatabase = DatabaseFactory.getSessionContactDatabase(context)
val contactDatabase = DatabaseComponent.get(context).sessionContactDatabase()
var contact = contactDatabase.getContactWithSessionID(sessionID)
if (contact == null) contact = Contact(sessionID)
contact.threadID = DatabaseFactory.getStorage(context).getThreadId(recipient.address)
contact.threadID = DatabaseComponent.get(context).storage().getThreadId(recipient.address)
if (contact.nickname != nickname) {
contact.nickname = nickname
contactDatabase.setContact(contact)
@ -25,16 +25,16 @@ class ProfileManager : SSKEnvironment.ProfileManagerProtocol {
override fun setName(context: Context, recipient: Recipient, name: String) {
// New API
val sessionID = recipient.address.serialize()
val contactDatabase = DatabaseFactory.getSessionContactDatabase(context)
val contactDatabase = DatabaseComponent.get(context).sessionContactDatabase()
var contact = contactDatabase.getContactWithSessionID(sessionID)
if (contact == null) contact = Contact(sessionID)
contact.threadID = DatabaseFactory.getStorage(context).getThreadId(recipient.address)
contact.threadID = DatabaseComponent.get(context).storage().getThreadId(recipient.address)
if (contact.name != name) {
contact.name = name
contactDatabase.setContact(contact)
}
// Old API
val database = DatabaseFactory.getRecipientDatabase(context)
val database = DatabaseComponent.get(context).recipientDatabase()
database.setProfileName(recipient, name)
recipient.notifyListeners()
}
@ -43,10 +43,10 @@ class ProfileManager : SSKEnvironment.ProfileManagerProtocol {
val job = RetrieveProfileAvatarJob(recipient, profilePictureURL)
ApplicationContext.getInstance(context).jobManager.add(job)
val sessionID = recipient.address.serialize()
val contactDatabase = DatabaseFactory.getSessionContactDatabase(context)
val contactDatabase = DatabaseComponent.get(context).sessionContactDatabase()
var contact = contactDatabase.getContactWithSessionID(sessionID)
if (contact == null) contact = Contact(sessionID)
contact.threadID = DatabaseFactory.getStorage(context).getThreadId(recipient.address)
contact.threadID = DatabaseComponent.get(context).storage().getThreadId(recipient.address)
if (contact.profilePictureURL != profilePictureURL) {
contact.profilePictureURL = profilePictureURL
contactDatabase.setContact(contact)
@ -56,21 +56,21 @@ class ProfileManager : SSKEnvironment.ProfileManagerProtocol {
override fun setProfileKey(context: Context, recipient: Recipient, profileKey: ByteArray) {
// New API
val sessionID = recipient.address.serialize()
val contactDatabase = DatabaseFactory.getSessionContactDatabase(context)
val contactDatabase = DatabaseComponent.get(context).sessionContactDatabase()
var contact = contactDatabase.getContactWithSessionID(sessionID)
if (contact == null) contact = Contact(sessionID)
contact.threadID = DatabaseFactory.getStorage(context).getThreadId(recipient.address)
contact.threadID = DatabaseComponent.get(context).storage().getThreadId(recipient.address)
if (!contact.profilePictureEncryptionKey.contentEquals(profileKey)) {
contact.profilePictureEncryptionKey = profileKey
contactDatabase.setContact(contact)
}
// Old API
val database = DatabaseFactory.getRecipientDatabase(context)
val database = DatabaseComponent.get(context).recipientDatabase()
database.setProfileKey(recipient, profileKey)
}
override fun setUnidentifiedAccessMode(context: Context, recipient: Recipient, unidentifiedAccessMode: Recipient.UnidentifiedAccessMode) {
val database = DatabaseFactory.getRecipientDatabase(context)
val database = DatabaseComponent.get(context).recipientDatabase()
database.setUnidentifiedAccessMode(recipient, unidentifiedAccessMode)
}
}

View File

@ -5,8 +5,8 @@ import org.session.libsession.utilities.Address
import org.session.libsession.utilities.SSKEnvironment
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
class ReadReceiptManager: SSKEnvironment.ReadReceiptManagerProtocol {
@ -17,7 +17,7 @@ class ReadReceiptManager: SSKEnvironment.ReadReceiptManagerProtocol {
var address = Address.fromSerialized(fromRecipientId)
for (timestamp in sentTimestamps) {
Log.i("Loki", "Received encrypted read receipt: (XXXXX, $timestamp)")
DatabaseFactory.getMmsSmsDatabase(context).incrementReadReceiptCount(SyncMessageId(address, timestamp), readTimestamp)
DatabaseComponent.get(context).mmsSmsDatabase().incrementReadReceiptCount(SyncMessageId(address, timestamp), readTimestamp)
}
}
}

View File

@ -14,9 +14,8 @@ import org.session.libsession.messaging.sending_receiving.attachments.Attachment
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment;
import org.session.libsession.utilities.ServiceUtil;
import org.session.libsession.utilities.TextSecurePreferences;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import java.util.Collections;
import java.util.Set;
@ -61,14 +60,14 @@ public class AttachmentUtil {
{
AttachmentId attachmentId = attachment.getAttachmentId();
long mmsId = attachment.getMmsId();
int attachmentCount = DatabaseFactory.getAttachmentDatabase(context)
int attachmentCount = DatabaseComponent.get(context).attachmentDatabase()
.getAttachmentsForMessage(mmsId)
.size();
if (attachmentCount <= 1) {
DatabaseFactory.getMmsDatabase(context).deleteMessage(mmsId);
DatabaseComponent.get(context).mmsDatabase().deleteMessage(mmsId);
} else {
DatabaseFactory.getAttachmentDatabase(context).deleteAttachment(attachmentId);
DatabaseComponent.get(context).attachmentDatabase().deleteAttachment(attachmentId);
}
}

View File

@ -22,8 +22,8 @@ import org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference
import org.thoughtcrime.securesms.backup.FullBackupExporter
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.BackupFileRecord
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.service.LocalBackupListener
import java.io.IOException
import java.security.MessageDigest
@ -114,7 +114,7 @@ object BackupUtil {
@JvmStatic
fun getLastBackupTimeString(context: Context, locale: Locale): String {
val timestamp = DatabaseFactory.getLokiBackupFilesDatabase(context).getLastBackupFileTime()
val timestamp = DatabaseComponent.get(context).lokiBackupFilesDatabase().getLastBackupFileTime()
if (timestamp == null) {
return context.getString(R.string.BackupUtil_never)
}
@ -123,7 +123,7 @@ object BackupUtil {
@JvmStatic
fun getLastBackup(context: Context): BackupFileRecord? {
return DatabaseFactory.getLokiBackupFilesDatabase(context).getLastBackupFile()
return DatabaseComponent.get(context).lokiBackupFilesDatabase().getLastBackupFile()
}
@JvmStatic
@ -206,10 +206,10 @@ object BackupUtil {
try {
FullBackupExporter.export(context,
AttachmentSecretProvider.getInstance(context).getOrCreateAttachmentSecret(),
DatabaseFactory.getBackupDatabase(context),
fileUri,
backupPassword)
AttachmentSecretProvider.getInstance(context).orCreateAttachmentSecret,
DatabaseComponent.get(context).openHelper().readableDatabase,
fileUri,
backupPassword)
} catch (e: Exception) {
// Delete the backup file on any error.
DocumentsContract.deleteDocument(context.contentResolver, fileUri)
@ -217,7 +217,7 @@ object BackupUtil {
}
//TODO Use real file size.
val record = DatabaseFactory.getLokiBackupFilesDatabase(context)
val record = DatabaseComponent.get(context).lokiBackupFilesDatabase()
.insertBackupFile(BackupFileRecord(fileUri, -1, date))
Log.v(TAG, "A backup file was created: $fileUri")
@ -228,7 +228,7 @@ object BackupUtil {
@JvmStatic
@JvmOverloads
fun deleteAllBackupFiles(context: Context, except: Collection<BackupFileRecord>? = null) {
val db = DatabaseFactory.getLokiBackupFilesDatabase(context)
val db = DatabaseComponent.get(context).lokiBackupFilesDatabase()
db.getBackupFiles().forEach { record ->
if (except != null && except.contains(record)) return@forEach

View File

@ -5,19 +5,18 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.TaskStackBuilder;
import android.text.TextUtils;
import android.widget.Toast;
import org.session.libsession.utilities.recipients.Recipient;
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import network.loki.messenger.R;
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.session.libsession.utilities.recipients.Recipient;
public class CommunicationActions {
public static void startConversation(@NonNull Context context,
@ -28,7 +27,7 @@ public class CommunicationActions {
new AsyncTask<Void, Void, Long>() {
@Override
protected Long doInBackground(Void... voids) {
return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
return DatabaseComponent.get(context).threadDatabase().getOrCreateThreadIdFor(recipient);
}
@Override

View File

@ -1,14 +1,14 @@
package org.thoughtcrime.securesms.util
import android.content.Context
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
object ContactUtilities {
@JvmStatic
fun getAllContacts(context: Context): Set<Recipient> {
val threadDatabase = DatabaseFactory.getThreadDatabase(context)
val threadDatabase = DatabaseComponent.get(context).threadDatabase()
val cursor = threadDatabase.conversationList
val result = mutableSetOf<Recipient>()
threadDatabase.readerFor(cursor).use { reader ->

View File

@ -99,7 +99,7 @@ class IP2Country private constructor(private val context: Context) {
val bestMatchCountry = comps.lastOrNull { it.key <= Ipv4Int(ip) }?.let { (_, code) ->
if (code != null) {
countryToNames[code]
countryToNames[code] + " [" + ip + "]"
} else {
null
}
@ -126,4 +126,4 @@ class IP2Country private constructor(private val context: Context) {
}
}
// endregion
}
}

View File

@ -5,9 +5,10 @@ import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;
import network.loki.messenger.R;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import network.loki.messenger.R;
public class Trimmer {
@ -37,7 +38,7 @@ public class Trimmer {
@Override
protected Void doInBackground(Integer... params) {
DatabaseFactory.getThreadDatabase(context).trimAllThreads(params[0], this);
DatabaseComponent.get(context).threadDatabase().trimAllThreads(params[0], this);
return null;
}

View File

@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.video.exo;
import android.content.Context;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -12,7 +13,7 @@ import com.google.android.exoplayer2.upstream.TransferListener;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.mms.PartUriParser;
import java.io.EOFException;
@ -43,7 +44,7 @@ public class PartDataSource implements DataSource {
public long open(DataSpec dataSpec) throws IOException {
this.uri = dataSpec.uri;
AttachmentDatabase attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context);
AttachmentDatabase attachmentDatabase = DatabaseComponent.get(context).attachmentDatabase();
PartUriParser partUri = new PartUriParser(uri);
Attachment attachment = attachmentDatabase.getAttachment(partUri.getPartId());

View File

@ -227,6 +227,18 @@
android:gravity="center"
android:text="@string/activity_settings_survey_feedback" />
<TextView
android:padding="@dimen/small_spacing"
android:id="@+id/supportButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/medium_spacing"
android:textColor="@color/text"
android:textSize="@dimen/medium_font_size"
android:textStyle="bold"
android:gravity="center"
android:text="@string/activity_settings_support" />
<TextView
android:padding="@dimen/small_spacing"
android:id="@+id/helpTranslateButton"

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/default_dialog_background_inset"
android:gravity="center_horizontal"
android:orientation="vertical"
android:elevation="4dp"
android:padding="32dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/dialog_share_logs_title"
android:textColor="@color/text"
android:textStyle="bold"
android:textSize="@dimen/medium_font_size" />
<TextView
android:id="@+id/dialogDescriptionText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/large_spacing"
android:text="@string/dialog_share_logs_explanation"
android:textColor="@color/text"
android:textSize="@dimen/small_font_size"
android:textAlignment="center" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/large_spacing"
android:orientation="horizontal">
<Button
style="@style/Widget.Session.Button.Dialog.Unimportant"
android:id="@+id/cancelButton"
android:layout_width="0dp"
android:layout_height="@dimen/small_button_height"
android:layout_weight="1"
android:text="@string/cancel" />
<Button
style="@style/Widget.Session.Button.Dialog.Unimportant"
android:id="@+id/shareButton"
android:layout_width="0dp"
android:layout_height="@dimen/small_button_height"
android:layout_weight="1"
android:layout_marginStart="@dimen/medium_spacing"
android:text="@string/share" />
<com.github.ybq.android.spinkit.SpinKitView
style="@style/SpinKitView.Small.ThreeBounce"
android:id="@+id/progressBar"
android:layout_width="0dp"
android:layout_height="@dimen/small_button_height"
android:layout_weight="1"
app:SpinKit_Color="@color/accent"
android:visibility="gone" />
</LinearLayout>
</LinearLayout>

View File

@ -899,5 +899,8 @@
<string name="delete_message_for_everyone">Delete for everyone</string>
<string name="delete_message_for_me_and_recipient">Delete for me and %s</string>
<string name="activity_settings_survey_feedback">Feedback/Survey</string>
<string name="activity_settings_support">Support</string>
<string name="dialog_share_logs_title">Share Logs</string>
<string name="dialog_share_logs_explanation">Would you like to export your application logs to be able to share for troubleshooting?</string>
</resources>

View File

@ -5,7 +5,6 @@ import android.net.Uri
import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.messaging.jobs.AttachmentUploadJob
import org.session.libsession.messaging.jobs.Job
import org.session.libsession.messaging.jobs.MessageReceiveJob
import org.session.libsession.messaging.jobs.MessageSendJob
import org.session.libsession.messaging.messages.control.ConfigurationMessage
import org.session.libsession.messaging.messages.visible.Attachment
@ -43,7 +42,7 @@ interface StorageProtocol {
fun getAllPendingJobs(type: String): Map<String,Job?>
fun getAttachmentUploadJob(attachmentID: Long): AttachmentUploadJob?
fun getMessageSendJob(messageSendJobID: String): MessageSendJob?
fun getMessageReceiveJob(messageReceiveJobID: String): MessageReceiveJob?
fun getMessageReceiveJob(messageReceiveJobID: String): Job?
fun resumeMessageSendJobIfNeeded(messageSendJobID: String)
fun isJobCanceled(job: Job): Boolean

View File

@ -0,0 +1,120 @@
package org.session.libsession.messaging.jobs
import com.google.protobuf.ByteString
import nl.komponents.kovenant.Promise
import nl.komponents.kovenant.task
import org.session.libsession.messaging.sending_receiving.MessageReceiver
import org.session.libsession.messaging.sending_receiving.handle
import org.session.libsession.messaging.utilities.Data
import org.session.libsignal.protos.UtilProtos
import org.session.libsignal.utilities.Log
data class MessageReceiveParameters(
val data: ByteArray,
val serverHash: String? = null,
val openGroupMessageServerID: Long? = null
)
class BatchMessageReceiveJob(
val messages: List<MessageReceiveParameters>,
val openGroupID: String? = null
) : Job {
override var delegate: JobDelegate? = null
override var id: String? = null
override var failureCount: Int = 0
override val maxFailureCount: Int = 10
// Failure Exceptions must be retryable if they're a MessageReceiver.Error
val failures = mutableListOf<MessageReceiveParameters>()
companion object {
const val TAG = "BatchMessageReceiveJob"
const val KEY = "BatchMessageReceiveJob"
// Keys used for database storage
private val NUM_MESSAGES_KEY = "numMessages"
private val DATA_KEY = "data"
private val SERVER_HASH_KEY = "serverHash"
private val OPEN_GROUP_MESSAGE_SERVER_ID_KEY = "openGroupMessageServerID"
private val OPEN_GROUP_ID_KEY = "open_group_id"
}
override fun execute() {
executeAsync().get()
}
fun executeAsync(): Promise<Unit, Exception> {
return task {
messages.forEach { messageParameters ->
val (data, serverHash, openGroupMessageServerID) = messageParameters
try {
val (message, proto) = MessageReceiver.parse(data, openGroupMessageServerID)
message.serverHash = serverHash
MessageReceiver.handle(message, proto, this.openGroupID)
} catch (e: Exception) {
Log.e(TAG, "Couldn't receive message.", e)
if (e is MessageReceiver.Error && !e.isRetryable) {
Log.e(TAG, "Message failed permanently",e)
} else {
Log.e(TAG, "Message failed",e)
failures += messageParameters
}
}
}
if (failures.isEmpty()) {
handleSuccess()
} else {
handleFailure()
}
}
}
private fun handleSuccess() {
this.delegate?.handleJobSucceeded(this)
}
private fun handleFailure() {
this.delegate?.handleJobFailed(this, Exception("One or more jobs resulted in failure"))
}
override fun serialize(): Data {
val arraySize = messages.size
val dataArrays = UtilProtos.ByteArrayList.newBuilder()
.addAllContent(messages.map(MessageReceiveParameters::data).map(ByteString::copyFrom))
.build()
val serverHashes = messages.map { it.serverHash.orEmpty() }
val openGroupServerIds = messages.map { it.openGroupMessageServerID ?: -1L }
return Data.Builder()
.putInt(NUM_MESSAGES_KEY, arraySize)
.putByteArray(DATA_KEY, dataArrays.toByteArray())
.putString(OPEN_GROUP_ID_KEY, openGroupID)
.putLongArray(OPEN_GROUP_MESSAGE_SERVER_ID_KEY, openGroupServerIds.toLongArray())
.putStringArray(SERVER_HASH_KEY, serverHashes.toTypedArray())
.build()
}
override fun getFactoryKey(): String = KEY
class Factory : Job.Factory<BatchMessageReceiveJob> {
override fun create(data: Data): BatchMessageReceiveJob {
val numMessages = data.getInt(NUM_MESSAGES_KEY)
val dataArrays = data.getByteArray(DATA_KEY)
val contents =
UtilProtos.ByteArrayList.parseFrom(dataArrays).contentList.map(ByteString::toByteArray)
val serverHashes =
if (data.hasStringArray(SERVER_HASH_KEY)) data.getStringArray(SERVER_HASH_KEY) else arrayOf()
val openGroupMessageServerIDs = data.getLongArray(OPEN_GROUP_MESSAGE_SERVER_ID_KEY)
val openGroupID = data.getStringOrDefault(OPEN_GROUP_ID_KEY, null)
val parameters = (0 until numMessages).map { index ->
val data = contents[index]
val serverHash = serverHashes[index].let { if (it.isEmpty()) null else it }
val serverId = openGroupMessageServerIDs[index].let { if (it == -1L) null else it }
MessageReceiveParameters(data, serverHash, serverId)
}
return BatchMessageReceiveJob(parameters, openGroupID)
}
}
}

Some files were not shown because too many files have changed in this diff Show More