From e1c91ba4e25f9d6db582bbbe7cce871c83e29427 Mon Sep 17 00:00:00 2001 From: Hossain Khan Date: Fri, 3 Apr 2026 08:27:29 -0400 Subject: [PATCH] feat: migrate DI from Dagger/Anvil to Metro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace Dagger 2 + Anvil DI infrastructure with Metro framework. Changes: - Add AppGraph.kt: Metro @DependencyGraph replacing Dagger AppComponent - Remove AppComponent.kt, ActivityKey.kt, TrmnlAppComponentFactory.kt - Update all DI modules (CircuitModule, NetworkModule, DataStoreModule, WorkerModule) from Dagger @Module objects to Metro @ContributesTo interfaces - Update ApplicationContext qualifier to use dev.zacsweers.metro.Qualifier - Migrate TrmnlDisplayMirrorApp to MetroApplication pattern - Update MainActivity: ContributesMultibinding → ContributesIntoMap - Update all presenter files: dagger.assisted.* → dev.zacsweers.metro.* - Update all data/work files: javax.inject.Inject → dev.zacsweers.metro.Inject - Remove android:appComponentFactory from manifest (MetroX provides it) Closes #273 Closes #274 Closes #275 Closes #276 --- app/src/main/AndroidManifest.xml | 4 +- .../java/ink/trmnl/android/MainActivity.kt | 9 +- .../trmnl/android/TrmnlDisplayMirrorApp.kt | 19 ++-- .../trmnl/android/data/ImageMetadataStore.kt | 2 +- .../data/TrmnlDeviceConfigDataStore.kt | 4 +- .../android/data/TrmnlDisplayRepository.kt | 4 +- .../trmnl/android/data/TrmnlUserRepository.kt | 4 +- .../android/data/log/RefreshLogExporter.kt | 2 +- .../data/log/TrmnlRefreshLogManager.kt | 4 +- .../java/ink/trmnl/android/di/ActivityKey.kt | 12 --- .../java/ink/trmnl/android/di/AppComponent.kt | 34 ------ .../java/ink/trmnl/android/di/AppGraph.kt | 35 ++++++ .../trmnl/android/di/ApplicationContext.kt | 2 +- .../ink/trmnl/android/di/CircuitModule.kt | 22 ++-- .../ink/trmnl/android/di/DataStoreModule.kt | 10 +- .../ink/trmnl/android/di/NetworkModule.kt | 16 ++- .../android/di/TrmnlAppComponentFactory.kt | 100 ------------------ .../java/ink/trmnl/android/di/WorkerModule.kt | 10 +- .../android/ui/aboutapp/AppInfoScreen.kt | 6 +- .../devicemodel/DeviceModelSelectorScreen.kt | 6 +- .../ui/display/TrmnlMirrorDisplayScreen.kt | 6 +- .../ui/refreshlog/DisplayRefreshLogScreen.kt | 6 +- .../android/ui/settings/AppSettingsScreen.kt | 6 +- .../android/util/AndroidDeviceInfoProvider.kt | 4 +- .../android/work/TrmnlImageRefreshWorker.kt | 2 +- .../android/work/TrmnlImageUpdateManager.kt | 4 +- .../trmnl/android/work/TrmnlWorkScheduler.kt | 4 +- .../trmnl/android/work/TrmnlWorkerFactory.kt | 4 +- 28 files changed, 111 insertions(+), 230 deletions(-) delete mode 100644 app/src/main/java/ink/trmnl/android/di/ActivityKey.kt delete mode 100644 app/src/main/java/ink/trmnl/android/di/AppComponent.kt create mode 100644 app/src/main/java/ink/trmnl/android/di/AppGraph.kt delete mode 100644 app/src/main/java/ink/trmnl/android/di/TrmnlAppComponentFactory.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6c78770..403b77f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,7 +6,6 @@ + android:enableOnBackInvokedCallback="true"> ()) @ActivityKey(MainActivity::class) class MainActivity @Inject diff --git a/app/src/main/java/ink/trmnl/android/TrmnlDisplayMirrorApp.kt b/app/src/main/java/ink/trmnl/android/TrmnlDisplayMirrorApp.kt index dc70568..5ada93a 100644 --- a/app/src/main/java/ink/trmnl/android/TrmnlDisplayMirrorApp.kt +++ b/app/src/main/java/ink/trmnl/android/TrmnlDisplayMirrorApp.kt @@ -3,23 +3,23 @@ package ink.trmnl.android import android.app.Application import android.util.Log import androidx.work.Configuration -import ink.trmnl.android.di.AppComponent -import ink.trmnl.android.work.TrmnlWorkerFactory +import dev.zacsweers.metro.createGraphFactory +import dev.zacsweers.metrox.android.MetroAppComponentProviders +import dev.zacsweers.metrox.android.MetroApplication +import ink.trmnl.android.di.AppGraph import timber.log.Timber -import javax.inject.Inject /** * Application class for the app with key initializations. */ class TrmnlDisplayMirrorApp : Application(), + MetroApplication, Configuration.Provider { - private val appComponent: AppComponent by lazy { AppComponent.create(this) } + private val appGraph by lazy { createGraphFactory().create(this) } - fun appComponent(): AppComponent = appComponent - - @Inject - lateinit var workerFactory: TrmnlWorkerFactory + override val appComponentProviders: MetroAppComponentProviders + get() = appGraph override val workManagerConfiguration: Configuration get() { @@ -27,14 +27,13 @@ class TrmnlDisplayMirrorApp : return Configuration .Builder() .setMinimumLoggingLevel(if (BuildConfig.DEBUG) Log.DEBUG else Log.WARN) - .setWorkerFactory(workerFactory) + .setWorkerFactory(appGraph.workerFactory) .build() } override fun onCreate() { super.onCreate() installLoggingTree() - appComponent.inject(this) } private fun installLoggingTree() { diff --git a/app/src/main/java/ink/trmnl/android/data/ImageMetadataStore.kt b/app/src/main/java/ink/trmnl/android/data/ImageMetadataStore.kt index 0e12621..d62110d 100644 --- a/app/src/main/java/ink/trmnl/android/data/ImageMetadataStore.kt +++ b/app/src/main/java/ink/trmnl/android/data/ImageMetadataStore.kt @@ -8,6 +8,7 @@ import androidx.datastore.preferences.core.intPreferencesKey import androidx.datastore.preferences.core.longPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore +import dev.zacsweers.metro.Inject import ink.trmnl.android.di.ApplicationContext import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first @@ -15,7 +16,6 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.runBlocking import timber.log.Timber import java.time.Instant -import javax.inject.Inject private val Context.imageDataStore: DataStore by preferencesDataStore( name = "trmnl_image_metadata", diff --git a/app/src/main/java/ink/trmnl/android/data/TrmnlDeviceConfigDataStore.kt b/app/src/main/java/ink/trmnl/android/data/TrmnlDeviceConfigDataStore.kt index 1473a00..126214e 100644 --- a/app/src/main/java/ink/trmnl/android/data/TrmnlDeviceConfigDataStore.kt +++ b/app/src/main/java/ink/trmnl/android/data/TrmnlDeviceConfigDataStore.kt @@ -8,9 +8,10 @@ import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.longPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore -import com.squareup.anvil.annotations.optional.SingleIn import com.squareup.moshi.Moshi import com.squareup.moshi.Types +import dev.zacsweers.metro.Inject +import dev.zacsweers.metro.SingleIn import ink.trmnl.android.data.AppConfig.DEFAULT_REFRESH_INTERVAL_SEC import ink.trmnl.android.data.AppConfig.TRMNL_API_SERVER_BASE_URL import ink.trmnl.android.di.AppScope @@ -24,7 +25,6 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.runBlocking import timber.log.Timber -import javax.inject.Inject /** * DataStore for managing TRMNL device configuration. diff --git a/app/src/main/java/ink/trmnl/android/data/TrmnlDisplayRepository.kt b/app/src/main/java/ink/trmnl/android/data/TrmnlDisplayRepository.kt index b1c2b01..9823305 100644 --- a/app/src/main/java/ink/trmnl/android/data/TrmnlDisplayRepository.kt +++ b/app/src/main/java/ink/trmnl/android/data/TrmnlDisplayRepository.kt @@ -2,7 +2,8 @@ package ink.trmnl.android.data import com.slack.eithernet.ApiResult import com.slack.eithernet.exceptionOrNull -import com.squareup.anvil.annotations.optional.SingleIn +import dev.zacsweers.metro.Inject +import dev.zacsweers.metro.SingleIn import ink.trmnl.android.di.AppScope import ink.trmnl.android.model.SupportedDeviceModel import ink.trmnl.android.model.TrmnlDeviceConfig @@ -20,7 +21,6 @@ import ink.trmnl.android.util.AndroidDeviceInfoProvider import ink.trmnl.android.util.HTTP_500 import ink.trmnl.android.util.isHttpOk import timber.log.Timber -import javax.inject.Inject /** * Repository class responsible for fetching and mapping display data. diff --git a/app/src/main/java/ink/trmnl/android/data/TrmnlUserRepository.kt b/app/src/main/java/ink/trmnl/android/data/TrmnlUserRepository.kt index 697e78b..ff74cf1 100644 --- a/app/src/main/java/ink/trmnl/android/data/TrmnlUserRepository.kt +++ b/app/src/main/java/ink/trmnl/android/data/TrmnlUserRepository.kt @@ -2,7 +2,8 @@ package ink.trmnl.android.data import com.slack.eithernet.ApiResult import com.slack.eithernet.exceptionOrNull -import com.squareup.anvil.annotations.optional.SingleIn +import dev.zacsweers.metro.Inject +import dev.zacsweers.metro.SingleIn import ink.trmnl.android.di.AppScope import ink.trmnl.android.model.TrmnlDeviceConfig import ink.trmnl.android.network.TrmnlUserApiService @@ -11,7 +12,6 @@ import ink.trmnl.android.network.model.TrmnlUser import ink.trmnl.android.network.util.constructApiUrl import ink.trmnl.android.util.AndroidDeviceInfoProvider import timber.log.Timber -import javax.inject.Inject /** * Repository class for user-level TRMNL API operations. diff --git a/app/src/main/java/ink/trmnl/android/data/log/RefreshLogExporter.kt b/app/src/main/java/ink/trmnl/android/data/log/RefreshLogExporter.kt index 3bb7d8d..964f0ac 100644 --- a/app/src/main/java/ink/trmnl/android/data/log/RefreshLogExporter.kt +++ b/app/src/main/java/ink/trmnl/android/data/log/RefreshLogExporter.kt @@ -5,6 +5,7 @@ import android.content.Intent import android.widget.Toast import androidx.core.content.FileProvider import com.squareup.moshi.Moshi +import dev.zacsweers.metro.Inject import ink.trmnl.android.di.ApplicationContext import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -13,7 +14,6 @@ import java.io.File import java.text.SimpleDateFormat import java.time.Instant import java.util.Locale -import javax.inject.Inject /** * Handles exporting refresh logs to a JSON file and sharing it via Android's share intent. diff --git a/app/src/main/java/ink/trmnl/android/data/log/TrmnlRefreshLogManager.kt b/app/src/main/java/ink/trmnl/android/data/log/TrmnlRefreshLogManager.kt index 00a466d..87e1d29 100644 --- a/app/src/main/java/ink/trmnl/android/data/log/TrmnlRefreshLogManager.kt +++ b/app/src/main/java/ink/trmnl/android/data/log/TrmnlRefreshLogManager.kt @@ -2,7 +2,8 @@ package ink.trmnl.android.data.log import android.content.Context import androidx.datastore.core.DataStore -import com.squareup.anvil.annotations.optional.SingleIn +import dev.zacsweers.metro.Inject +import dev.zacsweers.metro.SingleIn import ink.trmnl.android.data.AppConfig.MAX_LOG_ENTRIES import ink.trmnl.android.data.HttpResponseMetadata import ink.trmnl.android.di.AppScope @@ -12,7 +13,6 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.map import timber.log.Timber -import javax.inject.Inject /** * Manages logs related to terminal refresh operations. diff --git a/app/src/main/java/ink/trmnl/android/di/ActivityKey.kt b/app/src/main/java/ink/trmnl/android/di/ActivityKey.kt deleted file mode 100644 index 0769bb9..0000000 --- a/app/src/main/java/ink/trmnl/android/di/ActivityKey.kt +++ /dev/null @@ -1,12 +0,0 @@ -package ink.trmnl.android.di - -import android.app.Activity -import dagger.MapKey -import kotlin.reflect.KClass - -/** - * A Dagger multi-binding key used for registering a [Activity] into the top level dagger graphs. - */ -@MapKey annotation class ActivityKey( - val value: KClass, -) diff --git a/app/src/main/java/ink/trmnl/android/di/AppComponent.kt b/app/src/main/java/ink/trmnl/android/di/AppComponent.kt deleted file mode 100644 index 5bfb2ea..0000000 --- a/app/src/main/java/ink/trmnl/android/di/AppComponent.kt +++ /dev/null @@ -1,34 +0,0 @@ -package ink.trmnl.android.di - -import android.app.Activity -import android.content.Context -import com.squareup.anvil.annotations.MergeComponent -import com.squareup.anvil.annotations.optional.SingleIn -import dagger.BindsInstance -import ink.trmnl.android.TrmnlDisplayMirrorApp -import javax.inject.Provider - -@MergeComponent( - scope = AppScope::class, - modules = [CircuitModule::class], -) -@SingleIn(AppScope::class) -interface AppComponent { - val activityProviders: Map, @JvmSuppressWildcards Provider> - - /** - * Injects dependencies into [TrmnlDisplayMirrorApp]. - */ - fun inject(app: TrmnlDisplayMirrorApp) - - @MergeComponent.Factory - interface Factory { - fun create( - @ApplicationContext @BindsInstance context: Context, - ): AppComponent - } - - companion object { - fun create(context: Context): AppComponent = DaggerAppComponent.factory().create(context) - } -} diff --git a/app/src/main/java/ink/trmnl/android/di/AppGraph.kt b/app/src/main/java/ink/trmnl/android/di/AppGraph.kt new file mode 100644 index 0000000..3e287d8 --- /dev/null +++ b/app/src/main/java/ink/trmnl/android/di/AppGraph.kt @@ -0,0 +1,35 @@ +package ink.trmnl.android.di + +import android.content.Context +import dev.zacsweers.metro.DependencyGraph +import dev.zacsweers.metro.Provides +import dev.zacsweers.metrox.android.MetroAppComponentProviders +import ink.trmnl.android.work.TrmnlWorkerFactory + +/** + * Metro dependency graph for the application. + * + * - [MetroAppComponentProviders] enables constructor injection of Activities via + * [dev.zacsweers.metrox.android.MetroAppComponentFactory]. + * - [TrmnlWorkerFactory] is exposed so [ink.trmnl.android.TrmnlDisplayMirrorApp] can + * configure WorkManager. + */ +@DependencyGraph(AppScope::class) +interface AppGraph : MetroAppComponentProviders { + val workerFactory: TrmnlWorkerFactory + + /** + * Re-exposes the raw [Context] with the [ApplicationContext] qualifier so that + * module contributors can inject it by qualifier. + */ + @Provides + @ApplicationContext + fun provideApplicationContext(context: Context): Context = context + + @DependencyGraph.Factory + fun interface Factory { + fun create( + @Provides context: Context, + ): AppGraph + } +} diff --git a/app/src/main/java/ink/trmnl/android/di/ApplicationContext.kt b/app/src/main/java/ink/trmnl/android/di/ApplicationContext.kt index 76541c1..8a03379 100644 --- a/app/src/main/java/ink/trmnl/android/di/ApplicationContext.kt +++ b/app/src/main/java/ink/trmnl/android/di/ApplicationContext.kt @@ -1,6 +1,6 @@ package ink.trmnl.android.di -import javax.inject.Qualifier +import dev.zacsweers.metro.Qualifier /** Qualifier to denote a `Context` that is specifically an Application context. */ @Qualifier annotation class ApplicationContext diff --git a/app/src/main/java/ink/trmnl/android/di/CircuitModule.kt b/app/src/main/java/ink/trmnl/android/di/CircuitModule.kt index 56f3965..730eccc 100644 --- a/app/src/main/java/ink/trmnl/android/di/CircuitModule.kt +++ b/app/src/main/java/ink/trmnl/android/di/CircuitModule.kt @@ -3,27 +3,27 @@ package ink.trmnl.android.di import com.slack.circuit.foundation.Circuit import com.slack.circuit.runtime.presenter.Presenter import com.slack.circuit.runtime.ui.Ui -import com.squareup.anvil.annotations.ContributesTo -import com.squareup.anvil.annotations.optional.SingleIn -import dagger.Module -import dagger.Provides -import dagger.multibindings.Multibinds +import dev.zacsweers.metro.ContributesTo +import dev.zacsweers.metro.Multibinds +import dev.zacsweers.metro.Provides +import dev.zacsweers.metro.SingleIn /** - * Dagger module that provides dependencies for the Circuit framework. + * Metro module that provides dependencies for the Circuit framework. */ @ContributesTo(AppScope::class) -@Module interface CircuitModule { /** - * Dagger multi-binding method that provides a set of Presenter.Factory instances. + * Metro multi-binding declaration for Presenter.Factory instances contributed via + * @ContributesIntoSet. */ - @Multibinds fun presenterFactories(): Set + @Multibinds val presenterFactories: Set /** - * Dagger multi-binding method that provides a set of Ui.Factory instances. + * Metro multi-binding declaration for Ui.Factory instances contributed via + * @ContributesIntoSet. */ - @Multibinds fun viewFactories(): Set + @Multibinds val viewFactories: Set companion object { /** diff --git a/app/src/main/java/ink/trmnl/android/di/DataStoreModule.kt b/app/src/main/java/ink/trmnl/android/di/DataStoreModule.kt index 5dfa3ee..0d34755 100644 --- a/app/src/main/java/ink/trmnl/android/di/DataStoreModule.kt +++ b/app/src/main/java/ink/trmnl/android/di/DataStoreModule.kt @@ -4,19 +4,17 @@ import android.content.Context import androidx.datastore.core.DataStore import androidx.datastore.core.DataStoreFactory import androidx.datastore.dataStoreFile -import com.squareup.anvil.annotations.ContributesTo -import com.squareup.anvil.annotations.optional.SingleIn -import dagger.Module -import dagger.Provides +import dev.zacsweers.metro.ContributesTo +import dev.zacsweers.metro.Provides +import dev.zacsweers.metro.SingleIn import ink.trmnl.android.data.log.TrmnlRefreshLogSerializer import ink.trmnl.android.data.log.TrmnlRefreshLogs import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob -@Module @ContributesTo(AppScope::class) -object DataStoreModule { +interface DataStoreModule { @Provides @SingleIn(AppScope::class) fun provideActivityLogDataStore( diff --git a/app/src/main/java/ink/trmnl/android/di/NetworkModule.kt b/app/src/main/java/ink/trmnl/android/di/NetworkModule.kt index 27280c1..ada4465 100644 --- a/app/src/main/java/ink/trmnl/android/di/NetworkModule.kt +++ b/app/src/main/java/ink/trmnl/android/di/NetworkModule.kt @@ -4,12 +4,11 @@ import android.content.Context import androidx.core.content.pm.PackageInfoCompat import com.slack.eithernet.integration.retrofit.ApiResultCallAdapterFactory import com.slack.eithernet.integration.retrofit.ApiResultConverterFactory -import com.squareup.anvil.annotations.ContributesTo -import com.squareup.anvil.annotations.optional.SingleIn import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory -import dagger.Module -import dagger.Provides +import dev.zacsweers.metro.ContributesTo +import dev.zacsweers.metro.Provides +import dev.zacsweers.metro.SingleIn import ink.trmnl.android.BuildConfig import ink.trmnl.android.network.RateLimitInterceptor import ink.trmnl.android.network.TrmnlApiService @@ -22,12 +21,11 @@ import retrofit2.converter.moshi.MoshiConverterFactory import java.io.File import java.util.concurrent.TimeUnit -@Module -@ContributesTo(AppScope::class) -object NetworkModule { - // Cache size for OkHttp (10 MB) - private const val CACHE_SIZE = 10 * 1024 * 1024L +// Cache size for OkHttp (10 MB) +private const val CACHE_SIZE = 10 * 1024 * 1024L +@ContributesTo(AppScope::class) +interface NetworkModule { @Provides @SingleIn(AppScope::class) fun provideRateLimitInterceptor(): RateLimitInterceptor = RateLimitInterceptor() diff --git a/app/src/main/java/ink/trmnl/android/di/TrmnlAppComponentFactory.kt b/app/src/main/java/ink/trmnl/android/di/TrmnlAppComponentFactory.kt deleted file mode 100644 index 14dbfe1..0000000 --- a/app/src/main/java/ink/trmnl/android/di/TrmnlAppComponentFactory.kt +++ /dev/null @@ -1,100 +0,0 @@ -package ink.trmnl.android.di - -import android.app.Activity -import android.app.Application -import android.content.Intent -import androidx.annotation.Keep -import androidx.core.app.AppComponentFactory -import ink.trmnl.android.TrmnlDisplayMirrorApp -import javax.inject.Provider - -/** - * Custom implementation of [AppComponentFactory] used to inject Android components - * (specifically Activities) via Dagger using constructor injection. This factory - * allows the Android system to delegate activity instantiation to Dagger's dependency - * graph, enabling constructor injection instead of field injection. - * - * This class is referenced in the `AndroidManifest` within the `` tag. - * - * Usage: - * Add the following to your AndroidManifest.xml: - * - * ```xml - * - * ``` - */ -@Keep -class TrmnlAppComponentFactory : AppComponentFactory() { - /** - * Retrieves an instance of the specified class (typically an Activity) from the provided - * Dagger providers map. If a provider exists for the class, it uses that provider to - * obtain the instance; otherwise, it returns null. - * - * @param T The type of the class being retrieved. - * @param classLoader The ClassLoader used to load the class. - * @param className The fully qualified name of the class to be instantiated. - * @param providers A map containing Dagger providers for the available classes. - * @return The instance of the class if found in the providers map, or null if not. - */ - private inline fun getInstance( - classLoader: ClassLoader, - className: String, - providers: Map, @JvmSuppressWildcards Provider>, - ): T? { - // Load the class using the provided ClassLoader and attempt to retrieve the instance. - val clazz = Class.forName(className, false, classLoader).asSubclass(T::class.java) - val modelProvider = providers[clazz] ?: return null - return modelProvider.get() as T - } - - /** - * Called by the Android system to instantiate an activity. This method checks if the - * activity can be provided by the Dagger component. If the Dagger component can provide - * the activity, it returns the injected instance; otherwise, it falls back to the - * default system behavior. - * - * @param classLoader The ClassLoader used to load the activity class. - * @param className The fully qualified name of the activity to be instantiated. - * @param intent The intent that was used to start the activity. - * @return The activity instance, either from Dagger or from the system. - */ - override fun instantiateActivityCompat( - classLoader: ClassLoader, - className: String, - intent: Intent?, - ): Activity = - getInstance(classLoader, className, activityProviders) - ?: super.instantiateActivityCompat(classLoader, className, intent) - - /** - * Called by the Android system to instantiate the Application class. This method - * initializes the Dagger component and retrieves the map of activity providers, - * which are used later for activity injection. - * - * @param classLoader The ClassLoader used to load the Application class. - * @param className The fully qualified name of the Application class. - * @return The Application instance. - */ - override fun instantiateApplicationCompat( - classLoader: ClassLoader, - className: String, - ): Application { - val app = super.instantiateApplicationCompat(classLoader, className) - // Retrieve the Dagger app component and the activity providers from it - activityProviders = (app as TrmnlDisplayMirrorApp).appComponent().activityProviders - return app - } - - /** - * Companion object to store activity providers. This object holds the Dagger-provided - * map of activity classes to their corresponding providers. It's used to inject activities - * upon instantiation. - * - * This map is initialized when the application is created via the Dagger component. - */ - companion object { - private lateinit var activityProviders: Map, Provider> - } -} diff --git a/app/src/main/java/ink/trmnl/android/di/WorkerModule.kt b/app/src/main/java/ink/trmnl/android/di/WorkerModule.kt index 9f1a1e5..41e9034 100644 --- a/app/src/main/java/ink/trmnl/android/di/WorkerModule.kt +++ b/app/src/main/java/ink/trmnl/android/di/WorkerModule.kt @@ -3,15 +3,13 @@ package ink.trmnl.android.di import android.content.Context import androidx.work.Configuration import androidx.work.WorkManager -import com.squareup.anvil.annotations.ContributesTo -import com.squareup.anvil.annotations.optional.SingleIn -import dagger.Module -import dagger.Provides +import dev.zacsweers.metro.ContributesTo +import dev.zacsweers.metro.Provides +import dev.zacsweers.metro.SingleIn import ink.trmnl.android.work.TrmnlWorkerFactory -@Module @ContributesTo(AppScope::class) -object WorkerModule { +interface WorkerModule { @Provides @SingleIn(AppScope::class) fun provideWorkManager( diff --git a/app/src/main/java/ink/trmnl/android/ui/aboutapp/AppInfoScreen.kt b/app/src/main/java/ink/trmnl/android/ui/aboutapp/AppInfoScreen.kt index 2c7b2c2..286a1f5 100644 --- a/app/src/main/java/ink/trmnl/android/ui/aboutapp/AppInfoScreen.kt +++ b/app/src/main/java/ink/trmnl/android/ui/aboutapp/AppInfoScreen.kt @@ -37,9 +37,9 @@ import com.slack.circuit.runtime.CircuitUiState import com.slack.circuit.runtime.Navigator import com.slack.circuit.runtime.presenter.Presenter import com.slack.circuit.runtime.screen.Screen -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedFactory +import dev.zacsweers.metro.AssistedInject import ink.trmnl.android.BuildConfig import ink.trmnl.android.R import ink.trmnl.android.data.AppConfig.TRMNL_ANDROID_APP_GITHUB_URL diff --git a/app/src/main/java/ink/trmnl/android/ui/devicemodel/DeviceModelSelectorScreen.kt b/app/src/main/java/ink/trmnl/android/ui/devicemodel/DeviceModelSelectorScreen.kt index 45fdc49..6a8742f 100644 --- a/app/src/main/java/ink/trmnl/android/ui/devicemodel/DeviceModelSelectorScreen.kt +++ b/app/src/main/java/ink/trmnl/android/ui/devicemodel/DeviceModelSelectorScreen.kt @@ -43,9 +43,9 @@ import com.slack.circuit.runtime.Navigator import com.slack.circuit.runtime.presenter.Presenter import com.slack.circuit.runtime.screen.PopResult import com.slack.circuit.runtime.screen.Screen -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedFactory +import dev.zacsweers.metro.AssistedInject import ink.trmnl.android.data.AppConfig.TRMNL_API_SERVER_BASE_URL import ink.trmnl.android.data.TrmnlDisplayRepository import ink.trmnl.android.di.AppScope diff --git a/app/src/main/java/ink/trmnl/android/ui/display/TrmnlMirrorDisplayScreen.kt b/app/src/main/java/ink/trmnl/android/ui/display/TrmnlMirrorDisplayScreen.kt index 429be10..d69f454 100644 --- a/app/src/main/java/ink/trmnl/android/ui/display/TrmnlMirrorDisplayScreen.kt +++ b/app/src/main/java/ink/trmnl/android/ui/display/TrmnlMirrorDisplayScreen.kt @@ -47,9 +47,9 @@ import com.slack.circuit.runtime.CircuitUiState import com.slack.circuit.runtime.Navigator import com.slack.circuit.runtime.presenter.Presenter import com.slack.circuit.runtime.screen.Screen -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedFactory +import dev.zacsweers.metro.AssistedInject import ink.trmnl.android.R import ink.trmnl.android.data.AppConfig.AUTO_HIDE_APP_CONFIG_WINDOW_MS import ink.trmnl.android.data.ImageMetadataStore diff --git a/app/src/main/java/ink/trmnl/android/ui/refreshlog/DisplayRefreshLogScreen.kt b/app/src/main/java/ink/trmnl/android/ui/refreshlog/DisplayRefreshLogScreen.kt index 58ee516..ec224f8 100644 --- a/app/src/main/java/ink/trmnl/android/ui/refreshlog/DisplayRefreshLogScreen.kt +++ b/app/src/main/java/ink/trmnl/android/ui/refreshlog/DisplayRefreshLogScreen.kt @@ -55,9 +55,9 @@ import com.slack.circuit.runtime.CircuitUiState import com.slack.circuit.runtime.Navigator import com.slack.circuit.runtime.presenter.Presenter import com.slack.circuit.runtime.screen.Screen -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedFactory +import dev.zacsweers.metro.AssistedInject import ink.trmnl.android.BuildConfig import ink.trmnl.android.R import ink.trmnl.android.data.AppConfig.DEFAULT_REFRESH_INTERVAL_SEC diff --git a/app/src/main/java/ink/trmnl/android/ui/settings/AppSettingsScreen.kt b/app/src/main/java/ink/trmnl/android/ui/settings/AppSettingsScreen.kt index 51dcbfd..367c7ea 100644 --- a/app/src/main/java/ink/trmnl/android/ui/settings/AppSettingsScreen.kt +++ b/app/src/main/java/ink/trmnl/android/ui/settings/AppSettingsScreen.kt @@ -76,9 +76,9 @@ import com.slack.circuit.runtime.CircuitUiState import com.slack.circuit.runtime.Navigator import com.slack.circuit.runtime.presenter.Presenter import com.slack.circuit.runtime.screen.Screen -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedFactory +import dev.zacsweers.metro.AssistedInject import ink.trmnl.android.R import ink.trmnl.android.data.AppConfig.DEFAULT_REFRESH_INTERVAL_SEC import ink.trmnl.android.data.AppConfig.TRMNL_API_SERVER_BASE_URL diff --git a/app/src/main/java/ink/trmnl/android/util/AndroidDeviceInfoProvider.kt b/app/src/main/java/ink/trmnl/android/util/AndroidDeviceInfoProvider.kt index 610a199..3b51598 100644 --- a/app/src/main/java/ink/trmnl/android/util/AndroidDeviceInfoProvider.kt +++ b/app/src/main/java/ink/trmnl/android/util/AndroidDeviceInfoProvider.kt @@ -3,11 +3,11 @@ package ink.trmnl.android.util import android.content.Context import android.net.wifi.WifiManager import android.os.BatteryManager -import com.squareup.anvil.annotations.optional.SingleIn +import dev.zacsweers.metro.Inject +import dev.zacsweers.metro.SingleIn import ink.trmnl.android.di.AppScope import ink.trmnl.android.di.ApplicationContext import timber.log.Timber -import javax.inject.Inject /** * Provider class for accessing Android device information. diff --git a/app/src/main/java/ink/trmnl/android/work/TrmnlImageRefreshWorker.kt b/app/src/main/java/ink/trmnl/android/work/TrmnlImageRefreshWorker.kt index bc92059..99bc034 100644 --- a/app/src/main/java/ink/trmnl/android/work/TrmnlImageRefreshWorker.kt +++ b/app/src/main/java/ink/trmnl/android/work/TrmnlImageRefreshWorker.kt @@ -4,6 +4,7 @@ import android.content.Context import androidx.work.CoroutineWorker import androidx.work.WorkerParameters import androidx.work.workDataOf +import dev.zacsweers.metro.Inject import ink.trmnl.android.MainActivity import ink.trmnl.android.data.ImageMetadataStore import ink.trmnl.android.data.TrmnlDeviceConfigDataStore @@ -21,7 +22,6 @@ import ink.trmnl.android.work.RefreshWorkResult.SUCCESS import ink.trmnl.android.work.TrmnlWorkScheduler.Companion.IMAGE_REFRESH_PERIODIC_WORK_TAG import kotlinx.coroutines.flow.firstOrNull import timber.log.Timber -import javax.inject.Inject /** * Worker to refresh the image displayed on the TRMNL display. diff --git a/app/src/main/java/ink/trmnl/android/work/TrmnlImageUpdateManager.kt b/app/src/main/java/ink/trmnl/android/work/TrmnlImageUpdateManager.kt index 79314d1..f8eafaf 100644 --- a/app/src/main/java/ink/trmnl/android/work/TrmnlImageUpdateManager.kt +++ b/app/src/main/java/ink/trmnl/android/work/TrmnlImageUpdateManager.kt @@ -1,10 +1,10 @@ package ink.trmnl.android.work -import com.squareup.anvil.annotations.optional.SingleIn +import dev.zacsweers.metro.Inject +import dev.zacsweers.metro.SingleIn import ink.trmnl.android.data.ImageMetadata import ink.trmnl.android.data.ImageMetadataStore import ink.trmnl.android.di.AppScope -import jakarta.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow diff --git a/app/src/main/java/ink/trmnl/android/work/TrmnlWorkScheduler.kt b/app/src/main/java/ink/trmnl/android/work/TrmnlWorkScheduler.kt index 22714ea..c6f6734 100644 --- a/app/src/main/java/ink/trmnl/android/work/TrmnlWorkScheduler.kt +++ b/app/src/main/java/ink/trmnl/android/work/TrmnlWorkScheduler.kt @@ -13,7 +13,8 @@ import androidx.work.WorkInfo import androidx.work.WorkManager import androidx.work.WorkQuery import androidx.work.workDataOf -import com.squareup.anvil.annotations.optional.SingleIn +import dev.zacsweers.metro.Inject +import dev.zacsweers.metro.SingleIn import ink.trmnl.android.data.TrmnlDeviceConfigDataStore import ink.trmnl.android.di.AppScope import ink.trmnl.android.di.ApplicationContext @@ -23,7 +24,6 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import timber.log.Timber import java.util.concurrent.TimeUnit -import javax.inject.Inject /** * Manages the scheduling and execution of background work using WorkManager. diff --git a/app/src/main/java/ink/trmnl/android/work/TrmnlWorkerFactory.kt b/app/src/main/java/ink/trmnl/android/work/TrmnlWorkerFactory.kt index 6fa87b3..d0b73b2 100644 --- a/app/src/main/java/ink/trmnl/android/work/TrmnlWorkerFactory.kt +++ b/app/src/main/java/ink/trmnl/android/work/TrmnlWorkerFactory.kt @@ -4,9 +4,9 @@ import android.content.Context import androidx.work.ListenableWorker import androidx.work.WorkerFactory import androidx.work.WorkerParameters -import com.squareup.anvil.annotations.optional.SingleIn +import dev.zacsweers.metro.Inject +import dev.zacsweers.metro.SingleIn import ink.trmnl.android.di.AppScope -import javax.inject.Inject @SingleIn(AppScope::class) class TrmnlWorkerFactory