Skip to content
Snippets Groups Projects
Commit 1fba6c96 authored by Kamal Bramwell's avatar Kamal Bramwell
Browse files

Implemented BindingsRepository and BindingsModule

parent 934b135f
No related branches found
No related tags found
No related merge requests found
Showing
with 128 additions and 46 deletions
...@@ -4,6 +4,4 @@ import android.app.Application ...@@ -4,6 +4,4 @@ import android.app.Application
import dagger.hilt.android.HiltAndroidApp import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp @HiltAndroidApp
class MessengerApp : Application() { class MessengerApp : Application()
\ No newline at end of file
}
\ No newline at end of file
package io.elixxir.core.common package io.elixxir.core.common
import com.google.android.datatransport.runtime.dagger.Binds import dagger.Binds
import com.google.android.datatransport.runtime.dagger.Module import dagger.Module
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module @Module
@InstallIn(SingletonComponent::class) @InstallIn(SingletonComponent::class)
interface CommonModule { interface CommonModule {
@Singleton
@Binds @Binds
fun bindConfig( fun bindConfig(
config: DefaultConfig config: DefaultConfig
......
...@@ -40,7 +40,7 @@ kapt { ...@@ -40,7 +40,7 @@ kapt {
dependencies { dependencies {
implementation(project(":depconstraints")) implementation(project(":depconstraints"))
implementation(project(":xxclient")) api(project(":xxclient"))
implementation(project(":core:common")) implementation(project(":core:common"))
implementation(Libs.Core.ANDROIDX_APPCOMPAT) implementation(Libs.Core.ANDROIDX_APPCOMPAT)
......
package io.elixxir.data.networking
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import io.elixxir.data.networking.data.BindingsDataSource
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object BindingsModule {
@Singleton
@Provides
fun provideBindingsRepository(): BindingsRepository {
return BindingsDataSource()
}
}
\ No newline at end of file
package io.elixxir.data.networking
import io.elixxir.xxclient.bindings.Bindings
import io.elixxir.xxclient.cmix.CMix
/**
* A [Bindings] subclass that exposes a cached [CMix] reference.
*/
interface BindingsRepository : Bindings {
fun getCMix(): CMix?
}
\ No newline at end of file
package io.elixxir.data.networking package io.elixxir.data.networking
import dagger.Binds
import dagger.Module import dagger.Module
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent import dagger.hilt.components.SingletonComponent
import io.elixxir.data.networking.data.NetworkDataSource
import javax.inject.Singleton
@Module @Module
@InstallIn(SingletonComponent::class) @InstallIn(SingletonComponent::class)
interface NetworkModule { interface NetworkModule {
@Singleton
@Binds
fun bindNetworkRepository(
dataSource: NetworkDataSource
): NetworkRepository
} }
\ No newline at end of file
package io.elixxir.data.networking.data
import io.elixxir.data.networking.BindingsRepository
import io.elixxir.xxclient.bindings.BindingsAdapter
import io.elixxir.xxclient.cmix.CMix
import io.elixxir.xxclient.utils.CmixParams
import io.elixxir.xxclient.utils.Password
/**
* A [BindingsAdapter] subclass that exposes a cached [CMix] reference.
*/
internal class BindingsDataSource : BindingsAdapter(), BindingsRepository {
private var cMix: CMix? = null
override fun getCMix(): CMix? = cMix
override fun loadCmix(
sessionFileDirectory: String,
sessionPassword: Password,
cmixParams: CmixParams
): CMix {
return cMix ?: super.loadCmix(sessionFileDirectory, sessionPassword, cmixParams).apply {
cMix = this
}
}
}
\ No newline at end of file
package io.elixxir.data.networking.data package io.elixxir.data.networking.data
import io.elixxir.core.common.log import io.elixxir.core.common.Config
import kotlinx.coroutines.Dispatchers import io.elixxir.core.common.util.resultOf
import io.elixxir.data.networking.BindingsRepository
import io.elixxir.data.networking.NetworkRepository
import io.elixxir.xxclient.cmix.CMix
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import javax.inject.Inject
import kotlin.coroutines.resume import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine import kotlin.coroutines.suspendCoroutine
private const val MAX_NETWORK_RETRIES = 29 class NetworkDataSource @Inject internal constructor(
private const val NETWORK_POLL_INTERVAL_MS = 1000L private val bindings: BindingsRepository,
config: Config
) : NetworkRepository, Config by config {
class NetworkDataSource { private val cMix: CMix
get() = bindings.getCMix() ?: throw(IllegalStateException("CMix not initialized"))
private suspend fun connectToCmix(retries: Int = 0) { override suspend fun initializeNetwork(): Result<Unit> = resultOf {
networking.checkRegisterNetworkCallback() do {
if (retries < MAX_NETWORK_RETRIES) { waitTilHealthy()
if (initializeNetworkFollower()) {
log("Started network follower after #${retries + 1} attempt(s).")
withContext(Dispatchers.Main) {
onUsernameNextClicked()
}
} else {
delay(NETWORK_POLL_INTERVAL_MS) delay(NETWORK_POLL_INTERVAL_MS)
log("Attempting to start network follower, attempt #${retries + 1}.") } while (!waitTilHealthy())
connectToCmix(retries + 1)
} initializeNetworkFollower()
} else throw Exception("Failed to connect to network after ${retries + 1} attempts. Please try again.")
} }
private suspend fun initializeNetworkFollower(): Boolean = suspendCoroutine { continuation -> private suspend fun waitTilHealthy(): Boolean = suspendCoroutine { continuation ->
networking.tryStartNetworkFollower { successful -> continuation.resume(cMix.waitForNetwork(NETWORK_TIMEOUT_MS))
continuation.resume(successful)
} }
private suspend fun initializeNetworkFollower(): Unit = withContext(dispatcher) {
cMix.startNetworkFollower(NETWORK_TIMEOUT_MS)
} }
companion object {
private const val MAX_NETWORK_RETRIES = 29
private const val NETWORK_POLL_INTERVAL_MS = 1000L
private const val NETWORK_TIMEOUT_MS = 30_000L
}
} }
\ No newline at end of file
...@@ -40,8 +40,8 @@ kapt { ...@@ -40,8 +40,8 @@ kapt {
dependencies { dependencies {
implementation(project(":depconstraints")) implementation(project(":depconstraints"))
implementation(project(":xxclient"))
implementation(project(":core:common")) implementation(project(":core:common"))
implementation(project(":core:networking"))
implementation(project(":core:preferences")) implementation(project(":core:preferences"))
implementation(Libs.Core.ANDROIDX_APPCOMPAT) implementation(Libs.Core.ANDROIDX_APPCOMPAT)
......
...@@ -2,11 +2,16 @@ package io.elixxir.data.session ...@@ -2,11 +2,16 @@ package io.elixxir.data.session
import dagger.Binds import dagger.Binds
import dagger.Module import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent import dagger.hilt.components.SingletonComponent
import io.elixxir.core.common.Config
import io.elixxir.data.session.data.KeyStoreManager import io.elixxir.data.session.data.KeyStoreManager
import io.elixxir.data.session.data.SessionDataSource import io.elixxir.data.session.data.SessionDataSource
import io.elixxir.data.session.data.XxmKeyStore import io.elixxir.data.session.data.XxmKeyStore
import io.elixxir.xxclient.cmix.CMix
import kotlinx.coroutines.CoroutineScope
import javax.inject.Singleton
@Module @Module
@InstallIn(SingletonComponent::class) @InstallIn(SingletonComponent::class)
...@@ -17,6 +22,7 @@ interface SessionModule { ...@@ -17,6 +22,7 @@ interface SessionModule {
keyStore: XxmKeyStore keyStore: XxmKeyStore
): KeyStoreManager ): KeyStoreManager
@Singleton
@Binds @Binds
fun bindSessionRepository( fun bindSessionRepository(
repo: SessionDataSource, repo: SessionDataSource,
......
...@@ -6,7 +6,6 @@ import io.elixxir.core.common.Config ...@@ -6,7 +6,6 @@ import io.elixxir.core.common.Config
import io.elixxir.core.common.util.resultOf import io.elixxir.core.common.util.resultOf
import io.elixxir.data.session.SessionRepository import io.elixxir.data.session.SessionRepository
import io.elixxir.data.session.model.SessionState import io.elixxir.data.session.model.SessionState
import io.elixxir.xxclient.bindings.Bindings
import io.elixxir.xxclient.cmix.CMix import io.elixxir.xxclient.cmix.CMix
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.io.File import java.io.File
...@@ -14,7 +13,7 @@ import javax.inject.Inject ...@@ -14,7 +13,7 @@ import javax.inject.Inject
class SessionDataSource @Inject internal constructor( class SessionDataSource @Inject internal constructor(
@ApplicationContext private val context: Context, @ApplicationContext private val context: Context,
private val bindings: Bindings, private val bindings: BindingsRepository,
private val keyStore: KeyStoreManager, private val keyStore: KeyStoreManager,
config: Config, config: Config,
) : SessionRepository, Config by config { ) : SessionRepository, Config by config {
......
...@@ -5,9 +5,9 @@ import android.security.keystore.KeyGenParameterSpec ...@@ -5,9 +5,9 @@ import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties import android.security.keystore.KeyProperties
import io.elixxir.core.common.Config import io.elixxir.core.common.Config
import io.elixxir.core.preferences.model.KeyStorePreferences import io.elixxir.core.preferences.model.KeyStorePreferences
import io.elixxir.data.networking.BindingsRepository
import io.elixxir.data.session.util.fromBase64toByteArray import io.elixxir.data.session.util.fromBase64toByteArray
import io.elixxir.data.session.util.toBase64String import io.elixxir.data.session.util.toBase64String
import io.elixxir.xxclient.bindings.Bindings
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.lang.IllegalStateException import java.lang.IllegalStateException
import java.security.* import java.security.*
...@@ -20,7 +20,7 @@ import javax.inject.Inject ...@@ -20,7 +20,7 @@ import javax.inject.Inject
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
class XxmKeyStore @Inject internal constructor( class XxmKeyStore @Inject internal constructor(
private val bindings: Bindings, private val bindings: BindingsRepository,
private val prefs: KeyStorePreferences, private val prefs: KeyStorePreferences,
config: Config, config: Config,
) : KeyStoreManager, Config by config { ) : KeyStoreManager, Config by config {
......
...@@ -40,8 +40,8 @@ kapt { ...@@ -40,8 +40,8 @@ kapt {
dependencies { dependencies {
implementation(project(":depconstraints")) implementation(project(":depconstraints"))
implementation(project(":xxclient"))
implementation(project(":core:common")) implementation(project(":core:common"))
implementation(project(":core:networking"))
implementation(project(":core:preferences")) implementation(project(":core:preferences"))
implementation(Libs.Core.ANDROIDX_APPCOMPAT) implementation(Libs.Core.ANDROIDX_APPCOMPAT)
......
package io.elixxir.data.userdiscovery package io.elixxir.data.user
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.elixxir.data.userdiscovery"> package="io.elixxir.data.user">
</manifest> </manifest>
\ No newline at end of file
package io.elixxir.data.userdiscovery package io.elixxir.data.user
interface UserModule { interface UserModule {
......
package io.elixxir.data.userdiscovery package io.elixxir.data.user
interface UserRepository { interface UserRepository {
......
package io.elixxir.data.userdiscovery.data package io.elixxir.data.user.data
import io.elixxir.data.userdiscovery.UserRepository import io.elixxir.data.user.UserRepository
import javax.inject.Inject import javax.inject.Inject
class UserDataSource @Inject internal constructor(): UserRepository { class UserDataSource @Inject internal constructor(): UserRepository {
...@@ -33,5 +33,5 @@ class UserDataSource @Inject internal constructor(): UserRepository { ...@@ -33,5 +33,5 @@ class UserDataSource @Inject internal constructor(): UserRepository {
private fun displayError(errorMsg: String) { private fun displayError(errorMsg: String) {
error.postValue(bindingsErrorMessage(Exception(errorMsg))) error.postValue(bindingsErrorMessage(Exception(errorMsg)))
}
} }
\ No newline at end of file
package io.elixxir.data.userdiscovery package io.elixxir.data.user
import org.junit.Test import org.junit.Test
......
package io.elixxir.data.version.model package io.elixxir.data.version.model
import com.google.gson.JsonElement import com.google.gson.JsonElement
import io.elixxir.data.version.BuildConfig import io.elixxir.core.common.BuildConfig
internal data class VersionData( internal data class VersionData(
val cmixOldest: String = "", val cmixOldest: String = "",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment