Make injection of Rust data layer depend on a build time flag

This allows to build the project using the "local" Room data layer or
switching to the rust provided one.
The latter, is under development and (at this commit) implmentations are
mocked (leading to crashes at runtime). Making this dynamic allows to
keep both the old and new modules enabled (to import new changes from v6
without braking) and to keep UI tests on CI running.

ET-308
This commit is contained in:
Marino Meneghel
2024-06-25 11:59:01 +02:00
parent 485dfa8eb4
commit 5b1b26e09e
4 changed files with 108 additions and 63 deletions
+5
View File
@@ -46,6 +46,9 @@ private.properties
# Sentry properties
sentry.properties
# Rust lib build properties
rust.properties
# Test users credentials
**/users.json
**/internal_api.json
@@ -75,6 +78,8 @@ scripts/uitests/AssetsFile.lock.bak
.idea/**/shelf
.idea/runConfigurations.xml
.idea/misc.xml
.idea/deploymentTargetSelector.xml
.idea/other.xml
# Generated files
.idea/**/contentModel.xml
+20
View File
@@ -1,3 +1,5 @@
import java.util.Properties
/*
* Copyright (c) 2022 Proton Technologies AG
* This file is part of Proton Technologies AG and Proton Mail.
@@ -23,6 +25,18 @@ plugins {
kotlin("plugin.serialization") version Versions.Gradle.kotlinGradlePlugin
}
val rustProperties = Properties().apply {
@Suppress("SwallowedException")
try {
load(rootDir.resolve("rust.properties").inputStream())
} catch (exception: java.io.FileNotFoundException) {
// Provide empty properties to allow the app to be built without secrets
Properties()
}
}
val useRustDataLayer: String = rustProperties.getProperty("useRustDataLayer") ?: "false"
android {
namespace = "ch.protonmail.android.mailcommon.data"
compileSdk = Config.compileSdk
@@ -30,6 +44,8 @@ android {
defaultConfig {
minSdk = Config.minSdk
lint.targetSdk = Config.targetSdk
buildConfigField("Boolean", "USE_RUST_DATA_LAYER", useRustDataLayer)
}
compileOptions {
@@ -40,6 +56,10 @@ android {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
}
buildFeatures {
buildConfig = true
}
}
dependencies {
@@ -18,6 +18,7 @@
package ch.protonmail.android.mailconversation.dagger
import ch.protonmail.android.mailcommon.data.BuildConfig
import ch.protonmail.android.mailcommon.data.worker.Enqueuer
import ch.protonmail.android.mailcommon.domain.benchmark.BenchmarkTracer
import ch.protonmail.android.mailconversation.data.local.ConversationDatabase
@@ -27,12 +28,15 @@ import ch.protonmail.android.mailconversation.data.local.UnreadConversationsCoun
import ch.protonmail.android.mailconversation.data.remote.ConversationRemoteDataSourceImpl
import ch.protonmail.android.mailconversation.data.remote.UnreadConversationsCountRemoteDataSource
import ch.protonmail.android.mailconversation.data.remote.UnreadConversationsCountRemoteDataSourceImpl
import ch.protonmail.android.mailconversation.data.repository.ConversationRepositoryImpl
import ch.protonmail.android.mailconversation.data.repository.RustConversationRepositoryImpl
import ch.protonmail.android.mailconversation.data.repository.UnreadConversationsCountRepositoryImpl
import ch.protonmail.android.mailconversation.domain.repository.ConversationLocalDataSource
import ch.protonmail.android.mailconversation.domain.repository.ConversationRemoteDataSource
import ch.protonmail.android.mailconversation.domain.repository.ConversationRepository
import ch.protonmail.android.mailconversation.domain.repository.UnreadConversationsCountRepository
import ch.protonmail.android.mailmessage.data.local.MessageLocalDataSource
import ch.protonmail.android.mailmessage.data.usecase.ExcludeDraftMessagesAlreadyInOutbox
import dagger.Binds
import dagger.Module
import dagger.Provides
@@ -40,32 +44,34 @@ import dagger.Reusable
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import me.proton.core.network.data.ApiProvider
import me.proton.core.util.kotlin.CoroutineScopeProvider
import javax.inject.Singleton
@Module(includes = [MailConversationModule.BindsModule::class])
@InstallIn(SingletonComponent::class)
object MailConversationModule {
// @Provides
// @Singleton
// fun provideConversationRepositoryImpl(
// conversationLocalDataSource: ConversationLocalDataSource,
// conversationRemoteDataSource: ConversationRemoteDataSource,
// coroutineScopeProvider: CoroutineScopeProvider,
// messageLocalDataSource: MessageLocalDataSource,
// excludeDraftMessagesAlreadyInOutbox: ExcludeDraftMessagesAlreadyInOutbox
// ): ConversationRepository = ConversationRepositoryImpl(
// conversationRemoteDataSource = conversationRemoteDataSource,
// conversationLocalDataSource = conversationLocalDataSource,
// coroutineScopeProvider = coroutineScopeProvider,
// messageLocalDataSource = messageLocalDataSource,
// excludeDraftMessagesAlreadyInOutbox = excludeDraftMessagesAlreadyInOutbox
// )
@Provides
@Singleton
fun provideRustConversationRepository(): ConversationRepository = RustConversationRepositoryImpl()
fun provideConversationRepositoryImpl(
conversationLocalDataSource: ConversationLocalDataSource,
conversationRemoteDataSource: ConversationRemoteDataSource,
coroutineScopeProvider: CoroutineScopeProvider,
messageLocalDataSource: MessageLocalDataSource,
excludeDraftMessagesAlreadyInOutbox: ExcludeDraftMessagesAlreadyInOutbox
): ConversationRepository {
return if (BuildConfig.USE_RUST_DATA_LAYER) {
RustConversationRepositoryImpl()
} else {
ConversationRepositoryImpl(
conversationRemoteDataSource = conversationRemoteDataSource,
conversationLocalDataSource = conversationLocalDataSource,
coroutineScopeProvider = coroutineScopeProvider,
messageLocalDataSource = messageLocalDataSource,
excludeDraftMessagesAlreadyInOutbox = excludeDraftMessagesAlreadyInOutbox
)
}
}
@Provides
@Singleton
@@ -18,6 +18,7 @@
package ch.protonmail.android.mailmessage.dagger
import ch.protonmail.android.mailcommon.data.BuildConfig
import ch.protonmail.android.mailmessage.data.local.MessageLocalDataSource
import ch.protonmail.android.mailmessage.data.local.MessageLocalDataSourceImpl
import ch.protonmail.android.mailmessage.data.local.SearchResultsLocalDataSource
@@ -28,76 +29,89 @@ import ch.protonmail.android.mailmessage.data.remote.MessageRemoteDataSource
import ch.protonmail.android.mailmessage.data.remote.MessageRemoteDataSourceImpl
import ch.protonmail.android.mailmessage.data.remote.UnreadMessagesCountRemoteDataSource
import ch.protonmail.android.mailmessage.data.remote.UnreadMessagesCountRemoteDataSourceImpl
import ch.protonmail.android.mailmessage.data.repository.MessageRepositoryImpl
import ch.protonmail.android.mailmessage.data.repository.OutboxRepositoryImpl
import ch.protonmail.android.mailmessage.data.repository.RustMessageRepositoryImpl
import ch.protonmail.android.mailmessage.data.repository.SearchResultsRepositoryImpl
import ch.protonmail.android.mailmessage.data.repository.UnreadMessageCountRepositoryImpl
import ch.protonmail.android.mailmessage.data.usecase.ExcludeDraftMessagesAlreadyInOutbox
import ch.protonmail.android.mailmessage.domain.repository.MessageRepository
import ch.protonmail.android.mailmessage.domain.repository.OutboxRepository
import ch.protonmail.android.mailmessage.domain.repository.SearchResultsRepository
import ch.protonmail.android.mailmessage.domain.repository.UnreadMessagesCountRepository
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.Reusable
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import me.proton.core.util.kotlin.CoroutineScopeProvider
import javax.inject.Singleton
@Module
@Module(includes = [MailMessageModule.BindsModule::class])
@InstallIn(SingletonComponent::class)
abstract class MailMessageModule {
object MailMessageModule {
/*
* Rust data sources
*/
@Binds
@Provides
@Singleton
abstract fun provideMessageRepositoryImpl(repositoryImpl: RustMessageRepositoryImpl): MessageRepository
fun providesMessageRepository(
messageRemoteDataSource: MessageRemoteDataSource,
messageLocalDataSource: MessageLocalDataSource,
excludeDraftMessagesAlreadyInOutbox: ExcludeDraftMessagesAlreadyInOutbox,
coroutineScopeProvider: CoroutineScopeProvider
): MessageRepository {
return if (BuildConfig.USE_RUST_DATA_LAYER) {
RustMessageRepositoryImpl()
} else {
MessageRepositoryImpl(
messageRemoteDataSource,
messageLocalDataSource,
excludeDraftMessagesAlreadyInOutbox,
coroutineScopeProvider
)
}
}
/*
* Local data sources
*/
// @Binds
// @Singleton
// abstract fun provideMessageRepositoryImpl(repositoryImpl: MessageRepositoryImpl): MessageRepository
@Module
@InstallIn(SingletonComponent::class)
internal interface BindsModule {
@Binds
@Singleton
abstract fun provideMessageRemoteDataSource(remoteDataSource: MessageRemoteDataSourceImpl): MessageRemoteDataSource
@Binds
@Singleton
fun provideMessageRemoteDataSource(remoteDataSource: MessageRemoteDataSourceImpl): MessageRemoteDataSource
@Binds
@Singleton
abstract fun provideMessageLocalDataSource(localDataSourceImpl: MessageLocalDataSourceImpl): MessageLocalDataSource
@Binds
@Singleton
fun provideMessageLocalDataSource(localDataSourceImpl: MessageLocalDataSourceImpl): MessageLocalDataSource
@Binds
@Singleton
abstract fun provideOutboxRepositoryImpl(repositoryImpl: OutboxRepositoryImpl): OutboxRepository
@Binds
@Singleton
fun provideOutboxRepositoryImpl(repositoryImpl: OutboxRepositoryImpl): OutboxRepository
@Binds
@Singleton
abstract fun provideSearchResultsRepository(repositoryImpl: SearchResultsRepositoryImpl): SearchResultsRepository
@Binds
@Singleton
fun provideSearchResultsRepository(repositoryImpl: SearchResultsRepositoryImpl): SearchResultsRepository
@Binds
@Singleton
abstract fun provideSearchResultsLocalDataSource(
localDataSourceImpl: SearchResultsLocalDataSourceImpl
): SearchResultsLocalDataSource
@Binds
@Singleton
fun provideSearchResultsLocalDataSource(
localDataSourceImpl: SearchResultsLocalDataSourceImpl
): SearchResultsLocalDataSource
@Binds
@Reusable
abstract fun bindsUnreadMessagesCountRepository(
impl: UnreadMessageCountRepositoryImpl
): UnreadMessagesCountRepository
@Binds
@Reusable
fun bindsUnreadMessagesCountRepository(impl: UnreadMessageCountRepositoryImpl): UnreadMessagesCountRepository
@Binds
@Reusable
abstract fun bindsUnreadMessagesCountRemoteDataSource(
impl: UnreadMessagesCountRemoteDataSourceImpl
): UnreadMessagesCountRemoteDataSource
@Binds
@Reusable
fun bindsUnreadMessagesCountRemoteDataSource(
impl: UnreadMessagesCountRemoteDataSourceImpl
): UnreadMessagesCountRemoteDataSource
@Binds
@Reusable
abstract fun bindsUnreadMessagesCountLocalDataSource(
impl: UnreadMessagesCountLocalDataSourceImpl
): UnreadMessagesCountLocalDataSource
@Binds
@Reusable
fun bindsUnreadMessagesCountLocalDataSource(
impl: UnreadMessagesCountLocalDataSourceImpl
): UnreadMessagesCountLocalDataSource
}
}