More DI fixes

This commit is contained in:
ThomasSession 2024-10-02 15:38:46 +10:00 committed by SessionHero01
parent 7f008b5f1b
commit 2523975462
No known key found for this signature in database
10 changed files with 118 additions and 73 deletions

View File

@ -113,6 +113,7 @@ import javax.inject.Inject;
import dagger.hilt.EntryPoints;
import dagger.hilt.android.HiltAndroidApp;
import kotlin.Deprecated;
import kotlin.Unit;
import network.loki.messenger.BuildConfig;
import network.loki.messenger.R;
@ -132,11 +133,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
private static final String TAG = ApplicationContext.class.getSimpleName();
private ExpiringMessageManager expiringMessageManager;
private TypingStatusRepository typingStatusRepository;
private TypingStatusSender typingStatusSender;
private ReadReceiptManager readReceiptManager;
public MessageNotifier messageNotifier = null;
public Poller poller = null;
public Broadcaster broadcaster = null;
@ -154,8 +150,7 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
@Inject PollerFactory pollerFactory;
@Inject LastSentTimestampCache lastSentTimestampCache;
@Inject VersionDataFetcher versionDataFetcher;
@Inject
PushRegistrationHandler pushRegistrationHandler;
@Inject PushRegistrationHandler pushRegistrationHandler;
@Inject TokenFetcher tokenFetcher;
@Inject GroupManagerV2 groupManagerV2;
@Inject SSKEnvironment.ProfileManagerProtocol profileManager;
@ -165,6 +160,11 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
@Inject ConfigToDatabaseSync configToDatabaseSync;
@Inject RemoveGroupMemberHandler removeGroupMemberHandler;
@Inject SnodeClock snodeClock;
@Inject ExpiringMessageManager expiringMessageManager;
@Inject TypingStatusRepository typingStatusRepository;
@Inject TypingStatusSender typingStatusSender;
@Inject ReadReceiptManager readReceiptManager;
private volatile boolean isAppVisible;
@ -253,12 +253,8 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
LokiAPIDatabase apiDB = getDatabaseComponent().lokiAPIDatabase();
boolean useTestNet = textSecurePreferences.getEnvironment() == Environment.TEST_NET;
SnodeModule.Companion.configure(apiDB, broadcaster, useTestNet);
initializeExpiringMessageManager();
initializeTypingStatusRepository();
initializeTypingStatusSender();
initializeReadReceiptManager();
initializePeriodicTasks();
SSKEnvironment.Companion.configure(getTypingStatusRepository(), getReadReceiptManager(), profileManager, messageNotifier, getExpiringMessageManager());
SSKEnvironment.Companion.configure(typingStatusRepository, readReceiptManager, profileManager, messageNotifier, expiringMessageManager);
initializeWebRtc();
initializeBlobProvider();
resubmitProfilePictureIfNeeded();
@ -341,22 +337,27 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
super.onTerminate();
}
@Deprecated(message = "Use proper DI to inject this component")
public ExpiringMessageManager getExpiringMessageManager() {
return expiringMessageManager;
}
@Deprecated(message = "Use proper DI to inject this component")
public TypingStatusRepository getTypingStatusRepository() {
return typingStatusRepository;
}
@Deprecated(message = "Use proper DI to inject this component")
public TypingStatusSender getTypingStatusSender() {
return typingStatusSender;
}
@Deprecated(message = "Use proper DI to inject this component")
public TextSecurePreferences getTextSecurePreferences() {
return textSecurePreferences;
}
@Deprecated(message = "Use proper DI to inject this component")
public ReadReceiptManager getReadReceiptManager() {
return readReceiptManager;
}
@ -404,22 +405,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionLogger(originalHandler));
}
private void initializeExpiringMessageManager() {
this.expiringMessageManager = new ExpiringMessageManager(this);
}
private void initializeTypingStatusRepository() {
this.typingStatusRepository = new TypingStatusRepository();
}
private void initializeReadReceiptManager() {
this.readReceiptManager = new ReadReceiptManager();
}
private void initializeTypingStatusSender() {
this.typingStatusSender = new TypingStatusSender(this);
}
private void initializePeriodicTasks() {
BackgroundPollWorker.schedulePeriodic(this);
}

View File

@ -3,31 +3,34 @@ 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.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;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Singleton;
@SuppressLint("UseSparseArrays")
@Singleton
public class TypingStatusSender {
private static final long REFRESH_TYPING_TIMEOUT = TimeUnit.SECONDS.toMillis(10);
private static final long PAUSE_TYPING_TIMEOUT = TimeUnit.SECONDS.toMillis(3);
private final Context context;
private final Map<Long, TimerPair> selfTypingTimers;
private final ThreadDatabase threadDatabase;
public TypingStatusSender(@NonNull Context context) {
this.context = context;
@Inject
public TypingStatusSender(ThreadDatabase threadDatabase) {
this.threadDatabase = threadDatabase;
this.selfTypingTimers = new HashMap<>();
}
@ -77,7 +80,6 @@ public class TypingStatusSender {
}
private void sendTyping(long threadId, boolean typingStarted) {
ThreadDatabase threadDatabase = DatabaseComponent.get(context).threadDatabase();
Recipient recipient = threadDatabase.getRecipientForThreadId(threadId);
if (recipient == null) { return; }
if (!SessionMetaProtocol.shouldSendTypingIndicator(recipient)) { return; }

View File

@ -45,6 +45,7 @@ import org.thoughtcrime.securesms.database.ThreadDatabase
import org.thoughtcrime.securesms.dependencies.PollerFactory
import org.thoughtcrime.securesms.groups.ClosedGroupManager
import org.thoughtcrime.securesms.groups.OpenGroupManager
import org.thoughtcrime.securesms.util.asSequence
import javax.inject.Inject
private const val TAG = "ConfigToDatabaseSync"
@ -237,29 +238,41 @@ class ConfigToDatabaseSync @Inject constructor(
}
val newClosedGroups = userGroups.allClosedGroupInfo()
val existingClosedGroups = storage.getAllGroups(includeInactive = true).filter { it.isClosedGroupV2 }
val existingClosedGroupThreads: Map<AccountId, Long> = threadDatabase.readerFor(threadDatabase.conversationList).use { reader ->
buildMap(reader.count) {
var current = reader.next
while (current != null) {
if (current.recipient?.isClosedGroupV2Recipient == true) {
put(AccountId(current.recipient.address.serialize()), current.threadId)
}
current = reader.next
}
}
}
val groupThreadsToKeep = hashMapOf<AccountId, Long>()
for (closedGroup in newClosedGroups) {
val recipient = Recipient.from(context, fromSerialized(closedGroup.groupAccountId.hexString), false)
storage.setRecipientApprovedMe(recipient, true)
storage.setRecipientApproved(recipient, !closedGroup.invited)
val threadId = storage.getOrCreateThreadIdFor(recipient.address)
groupThreadsToKeep[closedGroup.groupAccountId] = threadId
storage.setPinned(threadId, closedGroup.priority == PRIORITY_PINNED)
if (!closedGroup.invited) {
pollerFactory.pollerFor(closedGroup.groupAccountId)?.start()
}
}
val toRemove = existingClosedGroups.mapTo(hashSetOf()) { it.encodedId } - newClosedGroups.mapTo(hashSetOf()) { it.groupAccountId.hexString }
val toRemove = existingClosedGroupThreads - groupThreadsToKeep.keys
Log.d(TAG, "Removing ${toRemove.size} closed groups")
toRemove.forEach { encodedId ->
val threadId = storage.getThreadId(encodedId)
if (threadId != null) {
toRemove.forEach { (groupId, threadId) ->
pollerFactory.pollerFor(groupId)?.stop()
storage.removeClosedGroupThread(threadId)
}
pollerFactory.pollerFor(AccountId(encodedId))?.stop()
}
for (group in lgc) {
val groupId = GroupUtil.doubleEncodeGroupID(group.accountId)
val existingGroup = existingLegacyClosedGroups.firstOrNull { GroupUtil.doubleDecodeGroupId(it.encodedId) == group.accountId }

View File

@ -2,12 +2,16 @@ package org.thoughtcrime.securesms.dependencies
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.session.libsession.database.StorageProtocol
import org.session.libsession.utilities.SSKEnvironment
import org.session.libsignal.database.LokiAPIDatabaseProtocol
import org.thoughtcrime.securesms.database.LokiAPIDatabase
import org.thoughtcrime.securesms.database.Storage
import org.thoughtcrime.securesms.service.ExpiringMessageManager
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
@ -18,4 +22,8 @@ abstract class DatabaseBindings {
@Binds
abstract fun bindLokiAPIDatabaseProtocol(lokiAPIDatabase: LokiAPIDatabase): LokiAPIDatabaseProtocol
@Binds
abstract fun bindMessageExpirationManagerProtocol(manager: ExpiringMessageManager): SSKEnvironment.MessageExpirationManagerProtocol
}

View File

@ -7,14 +7,36 @@ import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import org.session.libsession.database.MessageDataProvider
import org.session.libsession.utilities.SSKEnvironment
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.AttachmentDatabase
import org.thoughtcrime.securesms.database.BlindedIdMappingDatabase
import org.thoughtcrime.securesms.database.ConfigDatabase
import org.thoughtcrime.securesms.database.DraftDatabase
import org.thoughtcrime.securesms.database.EmojiSearchDatabase
import org.thoughtcrime.securesms.database.ExpirationConfigurationDatabase
import org.thoughtcrime.securesms.database.GroupDatabase
import org.thoughtcrime.securesms.database.GroupMemberDatabase
import org.thoughtcrime.securesms.database.GroupReceiptDatabase
import org.thoughtcrime.securesms.database.LokiAPIDatabase
import org.thoughtcrime.securesms.database.LokiBackupFilesDatabase
import org.thoughtcrime.securesms.database.LokiMessageDatabase
import org.thoughtcrime.securesms.database.LokiThreadDatabase
import org.thoughtcrime.securesms.database.LokiUserDatabase
import org.thoughtcrime.securesms.database.MediaDatabase
import org.thoughtcrime.securesms.database.MmsDatabase
import org.thoughtcrime.securesms.database.MmsSmsDatabase
import org.thoughtcrime.securesms.database.PushDatabase
import org.thoughtcrime.securesms.database.ReactionDatabase
import org.thoughtcrime.securesms.database.RecipientDatabase
import org.thoughtcrime.securesms.database.SearchDatabase
import org.thoughtcrime.securesms.database.SessionContactDatabase
import org.thoughtcrime.securesms.database.SessionJobDatabase
import org.thoughtcrime.securesms.database.SmsDatabase
import org.thoughtcrime.securesms.database.ThreadDatabase
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.service.ExpiringMessageManager
import javax.inject.Singleton
@Module
@ -26,10 +48,6 @@ object DatabaseModule {
System.loadLibrary("sqlcipher")
}
@Provides
@Singleton
fun provideMessageExpirationManagerProtocol(@ApplicationContext context: Context): SSKEnvironment.MessageExpirationManagerProtocol = ExpiringMessageManager(context)
@Provides
@Singleton
fun provideAttachmentSecret(@ApplicationContext context: Context) = AttachmentSecretProvider.getInstance(context).orCreateAttachmentSecret

View File

@ -6,6 +6,7 @@ import android.content.Context
import android.content.Intent
import android.os.AsyncTask
import androidx.core.app.NotificationManagerCompat
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.session.libsession.database.userAuth
@ -27,6 +28,7 @@ import org.thoughtcrime.securesms.database.MarkedMessageInfo
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.util.SessionMetaProtocol.shouldSendReadReceipt
@AndroidEntryPoint
class MarkReadReceiver : BroadcastReceiver() {
@SuppressLint("StaticFieldLeak")
override fun onReceive(context: Context, intent: Intent) {

View File

@ -1,13 +1,13 @@
package org.thoughtcrime.securesms.service
import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
import network.loki.messenger.libsession_util.util.ExpiryMode
import network.loki.messenger.libsession_util.util.ExpiryMode.AfterSend
import org.session.libsession.messaging.MessagingModuleConfiguration.Companion.shared
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.snode.SnodeAPI.nowWithOffset
import org.session.libsession.snode.SnodeClock
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.Address.Companion.fromSerialized
import org.session.libsession.utilities.GroupUtil
@ -23,27 +23,30 @@ import org.session.libsignal.utilities.guava.Optional
import org.thoughtcrime.securesms.database.MmsDatabase
import org.thoughtcrime.securesms.database.MmsSmsDatabase
import org.thoughtcrime.securesms.database.SmsDatabase
import org.thoughtcrime.securesms.dependencies.DatabaseComponent.Companion.get
import org.thoughtcrime.securesms.database.Storage
import org.thoughtcrime.securesms.mms.MmsException
import java.io.IOException
import java.util.TreeSet
import java.util.concurrent.Executor
import java.util.concurrent.Executors
import javax.inject.Inject
import javax.inject.Singleton
private val TAG = ExpiringMessageManager::class.java.simpleName
class ExpiringMessageManager(context: Context) : MessageExpirationManagerProtocol {
@Singleton
class ExpiringMessageManager @Inject constructor(
@ApplicationContext private val context: Context,
private val smsDatabase: SmsDatabase,
private val mmsDatabase: MmsDatabase,
private val mmsSmsDatabase: MmsSmsDatabase,
private val clock: SnodeClock,
private val storage: Storage,
) : MessageExpirationManagerProtocol {
private val expiringMessageReferences = TreeSet<ExpiringMessageReference>()
private val executor: Executor = Executors.newSingleThreadExecutor()
private val smsDatabase: SmsDatabase
private val mmsDatabase: MmsDatabase
private val mmsSmsDatabase: MmsSmsDatabase
private val context: Context
init {
this.context = context.applicationContext
smsDatabase = get(context).smsDatabase()
mmsDatabase = get(context).mmsDatabase()
mmsSmsDatabase = get(context).mmsSmsDatabase()
executor.execute(LoadTask())
executor.execute(ProcessTask())
}
@ -94,7 +97,7 @@ class ExpiringMessageManager(context: Context) : MessageExpirationManagerProtoco
}
recipient = Recipient.from(context, groupAddress, false)
}
val threadId = shared.storage.getThreadId(recipient) ?: return
val threadId = storage.getThreadId(recipient) ?: return
val mediaMessage = IncomingMediaMessage(
address, sentTimestamp!!, -1,
expiresInMillis, expireStartedAt, true,
@ -134,7 +137,7 @@ class ExpiringMessageManager(context: Context) : MessageExpirationManagerProtoco
val address = fromSerialized(serializedAddress)
val recipient = Recipient.from(context, address, false)
message.threadID = shared.storage.getOrCreateThreadIdFor(address)
message.threadID = storage.getOrCreateThreadIdFor(address)
val timerUpdateMessage = OutgoingExpirationUpdateMessage(
recipient,
sentTimestamp!!,
@ -206,7 +209,7 @@ class ExpiringMessageManager(context: Context) : MessageExpirationManagerProtoco
try {
while (expiringMessageReferences.isEmpty()) (expiringMessageReferences as Object).wait()
val nextReference = expiringMessageReferences.first()
val waitTime = nextReference.expiresAtMillis - nowWithOffset
val waitTime = nextReference.expiresAtMillis - clock.currentTimeMills()
if (waitTime > 0) {
ExpirationListener.setAlarm(context, waitTime)
(expiringMessageReferences as Object).wait(waitTime)

View File

@ -6,18 +6,24 @@ import org.session.libsession.utilities.SSKEnvironment
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.database.MmsSmsDatabase
import javax.inject.Inject
import javax.inject.Singleton
class ReadReceiptManager: SSKEnvironment.ReadReceiptManagerProtocol {
@Singleton
class ReadReceiptManager @Inject constructor(
private val textSecurePreferences: TextSecurePreferences,
private val mmsSmsDatabase: MmsSmsDatabase,
): SSKEnvironment.ReadReceiptManagerProtocol {
override fun processReadReceipts(context: Context, fromRecipientId: String, sentTimestamps: List<Long>, readTimestamp: Long) {
if (TextSecurePreferences.isReadReceiptsEnabled(context)) {
if (textSecurePreferences.isReadReceiptsEnabled()) {
// Redirect message to master device conversation
var address = Address.fromSerialized(fromRecipientId)
for (timestamp in sentTimestamps) {
Log.i("Loki", "Received encrypted read receipt: (XXXXX, $timestamp)")
DatabaseComponent.get(context).mmsSmsDatabase().incrementReadReceiptCount(SyncMessageId(address, timestamp), readTimestamp)
mmsSmsDatabase.incrementReadReceiptCount(SyncMessageId(address, timestamp), readTimestamp)
}
}
}

View File

@ -27,7 +27,11 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Singleton;
@SuppressLint("UseSparseArrays")
@Singleton
public class TypingStatusRepository implements SSKEnvironment.TypingIndicatorsProtocol {
private static final String TAG = TypingStatusRepository.class.getSimpleName();
@ -38,17 +42,20 @@ public class TypingStatusRepository implements SSKEnvironment.TypingIndicatorsPr
private final Map<Typist, Runnable> timers;
private final Map<Long, MutableLiveData<TypingState>> notifiers;
private final MutableLiveData<Set<Long>> threadsNotifier;
private final TextSecurePreferences preferences;
public TypingStatusRepository() {
@Inject
public TypingStatusRepository(TextSecurePreferences preferences) {
this.typistMap = new HashMap<>();
this.timers = new HashMap<>();
this.notifiers = new HashMap<>();
this.threadsNotifier = new MutableLiveData<>();
this.preferences = preferences;
}
@Override
public synchronized void didReceiveTypingStartedMessage(@NotNull Context context, long threadId, @NotNull Address author, int device) {
if (author.serialize().equals(TextSecurePreferences.getLocalNumber(context))) {
if (author.serialize().equals(preferences.getLocalNumber())) {
return;
}
@ -77,7 +84,7 @@ public class TypingStatusRepository implements SSKEnvironment.TypingIndicatorsPr
@Override
public synchronized void didReceiveTypingStoppedMessage(@NotNull Context context, long threadId, @NotNull Address author, int device, boolean isReplacedByIncomingMessage) {
if (author.serialize().equals(TextSecurePreferences.getLocalNumber(context))) {
if (author.serialize().equals(preferences.getLocalNumber())) {
return;
}

View File

@ -75,6 +75,7 @@ class SSKEnvironment(
}
companion object {
@Deprecated("Use Hilt to inject your dependencies instead")
lateinit var shared: SSKEnvironment
fun configure(typingIndicators: TypingIndicatorsProtocol,