Start migrating Anvil KSP to Metro

This commit is contained in:
Jorge Martín 2025-08-20 15:29:50 +02:00
parent d4d57b1e21
commit b76a71ebf5
703 changed files with 3523 additions and 2820 deletions

View file

@ -7,13 +7,13 @@
package io.element.android.services.analytics.impl
import com.squareup.anvil.annotations.ContributesBinding
import dev.zacsweers.metro.ContributesBinding
import im.vector.app.features.analytics.itf.VectorAnalyticsEvent
import im.vector.app.features.analytics.itf.VectorAnalyticsScreen
import im.vector.app.features.analytics.plan.SuperProperties
import im.vector.app.features.analytics.plan.UserProperties
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.SingleIn
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.SingleIn
import io.element.android.libraries.di.annotations.AppCoroutineScope
import io.element.android.libraries.sessionstorage.api.observer.SessionListener
import io.element.android.libraries.sessionstorage.api.observer.SessionObserver
@ -27,11 +27,13 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import timber.log.Timber
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject
import dev.zacsweers.metro.Inject
import dev.zacsweers.metro.binding
@SingleIn(AppScope::class)
@ContributesBinding(AppScope::class, boundType = AnalyticsService::class, rank = ContributesBinding.RANK_HIGHEST)
class DefaultAnalyticsService @Inject constructor(
@ContributesBinding(AppScope::class, binding = binding<AnalyticsService>())
@Inject
class DefaultAnalyticsService(
private val analyticsProviders: Set<@JvmSuppressWildcards AnalyticsProvider>,
private val analyticsStore: AnalyticsStore,
// private val lateInitUserPropertiesFactory: LateInitUserPropertiesFactory,

View file

@ -13,17 +13,18 @@ import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.lifecycle.Lifecycle
import com.squareup.anvil.annotations.ContributesBinding
import dev.zacsweers.metro.ContributesBinding
import im.vector.app.features.analytics.plan.MobileScreen
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
import io.element.android.libraries.di.AppScope
import dev.zacsweers.metro.AppScope
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analytics.api.ScreenTracker
import io.element.android.services.toolbox.api.systemclock.SystemClock
import javax.inject.Inject
import dev.zacsweers.metro.Inject
@ContributesBinding(AppScope::class)
class DefaultScreenTracker @Inject constructor(
@Inject
class DefaultScreenTracker(
private val analyticsService: AnalyticsService,
private val systemClock: SystemClock
) : ScreenTracker {

View file

@ -10,14 +10,14 @@ package io.element.android.services.analytics.impl.store
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import com.squareup.anvil.annotations.ContributesBinding
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding
import dev.zacsweers.metro.Inject
import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import javax.inject.Inject
/**
* Local storage for:
@ -36,7 +36,8 @@ interface AnalyticsStore {
}
@ContributesBinding(AppScope::class)
class DefaultAnalyticsStore @Inject constructor(
@Inject
class DefaultAnalyticsStore(
preferenceDataStoreFactory: PreferenceDataStoreFactory,
) : AnalyticsStore {
private val userConsent = booleanPreferencesKey("user_consent")

View file

@ -7,22 +7,23 @@
package io.element.android.services.analytics.noop
import com.squareup.anvil.annotations.ContributesBinding
import dev.zacsweers.metro.ContributesBinding
import im.vector.app.features.analytics.itf.VectorAnalyticsEvent
import im.vector.app.features.analytics.itf.VectorAnalyticsScreen
import im.vector.app.features.analytics.plan.SuperProperties
import im.vector.app.features.analytics.plan.UserProperties
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.SingleIn
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.SingleIn
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analyticsproviders.api.AnalyticsProvider
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import javax.inject.Inject
import dev.zacsweers.metro.Inject
@SingleIn(AppScope::class)
@ContributesBinding(AppScope::class)
class NoopAnalyticsService @Inject constructor() : AnalyticsService {
@Inject
class NoopAnalyticsService() : AnalyticsService {
override fun getAvailableAnalyticsProviders(): Set<AnalyticsProvider> = emptySet()
override val userConsentFlow: Flow<Boolean> = flowOf(false)
override suspend fun setUserConsent(userConsent: Boolean) = Unit

View file

@ -8,14 +8,15 @@
package io.element.android.services.analytics.noop
import androidx.compose.runtime.Composable
import com.squareup.anvil.annotations.ContributesBinding
import dev.zacsweers.metro.ContributesBinding
import im.vector.app.features.analytics.plan.MobileScreen
import io.element.android.libraries.di.AppScope
import dev.zacsweers.metro.AppScope
import io.element.android.services.analytics.api.ScreenTracker
import javax.inject.Inject
import dev.zacsweers.metro.Inject
@ContributesBinding(AppScope::class)
class NoopScreenTracker @Inject constructor() : ScreenTracker {
@Inject
class NoopScreenTracker() : ScreenTracker {
@Composable
override fun TrackScreen(screen: MobileScreen.ScreenName) = Unit
}

View file

@ -12,10 +12,11 @@ import com.posthog.PostHogInterface
import com.posthog.android.PostHogAndroid
import com.posthog.android.PostHogAndroidConfig
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.di.ApplicationContext
import javax.inject.Inject
import io.element.android.libraries.di.annotations.ApplicationContext
import dev.zacsweers.metro.Inject
class PostHogFactory @Inject constructor(
@Inject
class PostHogFactory(
@ApplicationContext private val context: Context,
private val buildMeta: BuildMeta,
private val posthogEndpointConfigProvider: PosthogEndpointConfigProvider,

View file

@ -8,22 +8,23 @@
package io.element.android.services.analyticsproviders.posthog
import com.posthog.PostHogInterface
import com.squareup.anvil.annotations.ContributesMultibinding
import dev.zacsweers.metro.ContributesIntoSet
import im.vector.app.features.analytics.itf.VectorAnalyticsEvent
import im.vector.app.features.analytics.itf.VectorAnalyticsScreen
import im.vector.app.features.analytics.plan.SuperProperties
import im.vector.app.features.analytics.plan.UserProperties
import io.element.android.libraries.di.AppScope
import dev.zacsweers.metro.AppScope
import io.element.android.services.analyticsproviders.api.AnalyticsProvider
import io.element.android.services.analyticsproviders.posthog.log.analyticsTag
import timber.log.Timber
import javax.inject.Inject
import dev.zacsweers.metro.Inject
// private val REUSE_EXISTING_ID: String? = null
// private val IGNORED_OPTIONS: Options? = null
@ContributesMultibinding(AppScope::class)
class PosthogAnalyticsProvider @Inject constructor(
@ContributesIntoSet(AppScope::class)
@Inject
class PosthogAnalyticsProvider(
private val postHogFactory: PostHogFactory,
) : AnalyticsProvider {
override val name = "Posthog"

View file

@ -11,9 +11,10 @@ import io.element.android.features.enterprise.api.EnterpriseService
import io.element.android.libraries.core.extensions.isElement
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.core.meta.BuildType
import javax.inject.Inject
import dev.zacsweers.metro.Inject
class PosthogEndpointConfigProvider @Inject constructor(
@Inject
class PosthogEndpointConfigProvider(
private val buildMeta: BuildMeta,
private val enterpriseService: EnterpriseService,
) {

View file

@ -8,15 +8,16 @@
package io.element.android.services.analyticsproviders.sentry
import android.content.Context
import com.squareup.anvil.annotations.ContributesMultibinding
import dev.zacsweers.metro.ContributesIntoSet
import dev.zacsweers.metro.Inject
import im.vector.app.features.analytics.itf.VectorAnalyticsEvent
import im.vector.app.features.analytics.itf.VectorAnalyticsScreen
import im.vector.app.features.analytics.plan.SuperProperties
import im.vector.app.features.analytics.plan.UserProperties
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.core.meta.BuildType
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
import dev.zacsweers.metro.AppScope
import io.element.android.libraries.di.annotations.ApplicationContext
import io.element.android.services.analyticsproviders.api.AnalyticsProvider
import io.element.android.services.analyticsproviders.sentry.log.analyticsTag
import io.sentry.Breadcrumb
@ -24,12 +25,10 @@ import io.sentry.Sentry
import io.sentry.SentryOptions
import io.sentry.android.core.SentryAndroid
import timber.log.Timber
import javax.inject.Inject
import kotlin.collections.component1
import kotlin.collections.component2
@ContributesMultibinding(AppScope::class)
class SentryAnalyticsProvider @Inject constructor(
@ContributesIntoSet(AppScope::class)
@Inject
class SentryAnalyticsProvider(
@ApplicationContext private val context: Context,
private val buildMeta: BuildMeta,
) : AnalyticsProvider {

View file

@ -7,19 +7,20 @@
package io.element.android.services.apperror.impl
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.SingleIn
import dev.zacsweers.metro.ContributesBinding
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.SingleIn
import io.element.android.services.apperror.api.AppErrorState
import io.element.android.services.apperror.api.AppErrorStateService
import io.element.android.services.toolbox.api.strings.StringProvider
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import javax.inject.Inject
import dev.zacsweers.metro.Inject
@ContributesBinding(AppScope::class)
@SingleIn(AppScope::class)
class DefaultAppErrorStateService @Inject constructor(
@Inject
class DefaultAppErrorStateService(
private val stringProvider: StringProvider,
) : AppErrorStateService {
private val currentAppErrorState = MutableStateFlow<AppErrorState>(AppErrorState.NoError)

View file

@ -1,3 +1,5 @@
import extension.setupAnvil
/*
* Copyright 2022-2024 New Vector Ltd.
*
@ -13,6 +15,8 @@ android {
namespace = "io.element.android.services.appnavstate.api"
}
setupAnvil()
dependencies {
implementation(libs.coroutines.core)
implementation(libs.androidx.lifecycle.runtime)

View file

@ -7,19 +7,20 @@
package io.element.android.services.appnavstate.api
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.SingleIn
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.SingleIn
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.room.JoinedRoom
import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
import dev.zacsweers.metro.Inject
/**
* Holds the active rooms for a given session so they can be reused instead of instantiating new ones.
*/
@SingleIn(AppScope::class)
class ActiveRoomsHolder @Inject constructor() {
@Inject
class ActiveRoomsHolder {
private val rooms = ConcurrentHashMap<SessionId, MutableSet<JoinedRoom>>()
/**

View file

@ -7,10 +7,10 @@
package io.element.android.services.appnavstate.impl
import com.squareup.anvil.annotations.ContributesBinding
import dev.zacsweers.metro.ContributesBinding
import io.element.android.libraries.core.log.logger.LoggerTag
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.SingleIn
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.SingleIn
import io.element.android.libraries.di.annotations.AppCoroutineScope
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.SessionId
@ -26,7 +26,7 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.getAndUpdate
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
import dev.zacsweers.metro.Inject
private val loggerTag = LoggerTag("Navigation")
@ -35,7 +35,8 @@ private val loggerTag = LoggerTag("Navigation")
*/
@ContributesBinding(AppScope::class)
@SingleIn(AppScope::class)
class DefaultAppNavigationStateService @Inject constructor(
@Inject
class DefaultAppNavigationStateService(
private val appForegroundStateService: AppForegroundStateService,
@AppCoroutineScope
coroutineScope: CoroutineScope,

View file

@ -9,15 +9,15 @@ package io.element.android.services.appnavstate.impl.di
import android.content.Context
import androidx.startup.AppInitializer
import com.squareup.anvil.annotations.ContributesTo
import dagger.Module
import dagger.Provides
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
import dev.zacsweers.metro.BindingContainer
import dev.zacsweers.metro.ContributesTo
import dev.zacsweers.metro.Provides
import dev.zacsweers.metro.AppScope
import io.element.android.libraries.di.annotations.ApplicationContext
import io.element.android.services.appnavstate.api.AppForegroundStateService
import io.element.android.services.appnavstate.impl.initializer.AppForegroundStateServiceInitializer
@Module
@BindingContainer
@ContributesTo(AppScope::class)
object AppNavStateModule {
@Provides

View file

@ -9,14 +9,15 @@ package io.element.android.services.toolbox.impl.intent
import android.content.Context
import android.content.Intent
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
import dev.zacsweers.metro.ContributesBinding
import dev.zacsweers.metro.AppScope
import io.element.android.libraries.di.annotations.ApplicationContext
import io.element.android.services.toolbox.api.intent.ExternalIntentLauncher
import javax.inject.Inject
import dev.zacsweers.metro.Inject
@ContributesBinding(AppScope::class)
class DefaultExternalIntentLauncher @Inject constructor(
@Inject
class DefaultExternalIntentLauncher(
@ApplicationContext private val context: Context,
) : ExternalIntentLauncher {
override fun launch(intent: Intent) {

View file

@ -8,13 +8,14 @@
package io.element.android.services.toolbox.impl.sdk
import android.os.Build
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope
import dev.zacsweers.metro.ContributesBinding
import dev.zacsweers.metro.AppScope
import io.element.android.services.toolbox.api.sdk.BuildVersionSdkIntProvider
import javax.inject.Inject
import dev.zacsweers.metro.Inject
@ContributesBinding(AppScope::class)
class DefaultBuildVersionSdkIntProvider @Inject constructor() :
@Inject
class DefaultBuildVersionSdkIntProvider() :
BuildVersionSdkIntProvider {
override fun get() = Build.VERSION.SDK_INT
}

View file

@ -10,13 +10,14 @@ package io.element.android.services.toolbox.impl.strings
import android.content.res.Resources
import androidx.annotation.PluralsRes
import androidx.annotation.StringRes
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope
import dev.zacsweers.metro.ContributesBinding
import dev.zacsweers.metro.AppScope
import io.element.android.services.toolbox.api.strings.StringProvider
import javax.inject.Inject
import dev.zacsweers.metro.Inject
@ContributesBinding(AppScope::class)
class AndroidStringProvider @Inject constructor(private val resources: Resources) : StringProvider {
@Inject
class AndroidStringProvider(private val resources: Resources) : StringProvider {
override fun getString(@StringRes resId: Int): String {
return resources.getString(resId)
}

View file

@ -7,13 +7,14 @@
package io.element.android.services.toolbox.impl.systemclock
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope
import dev.zacsweers.metro.ContributesBinding
import dev.zacsweers.metro.AppScope
import io.element.android.services.toolbox.api.systemclock.SystemClock
import javax.inject.Inject
import dev.zacsweers.metro.Inject
@ContributesBinding(AppScope::class)
class DefaultSystemClock @Inject constructor() : SystemClock {
@Inject
class DefaultSystemClock() : SystemClock {
/**
* Provides a UTC epoch in milliseconds
*

View file

@ -7,13 +7,13 @@
package io.element.android.services.toolbox.impl.systemclock
import com.squareup.anvil.annotations.ContributesTo
import dagger.Module
import dagger.Provides
import io.element.android.libraries.di.AppScope
import dev.zacsweers.metro.BindingContainer
import dev.zacsweers.metro.ContributesTo
import dev.zacsweers.metro.Provides
import dev.zacsweers.metro.AppScope
import kotlin.time.TimeSource
@Module
@BindingContainer
@ContributesTo(AppScope::class)
object TimeModule {
@Provides