refactor(di): replace Tangle with Whetstone

This commit is contained in:
Harsh Shandilya 2022-11-14 02:35:00 +05:30
parent 4a87682b68
commit 0232a4179a
No known key found for this signature in database
23 changed files with 36 additions and 188 deletions

View File

@ -48,8 +48,6 @@ android {
}
dependencies {
anvil(libs.tangle.viewmodel.compiler)
anvil(libs.tangle.work.compiler)
kapt(libs.dagger.compiler)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.dagger)
@ -58,7 +56,6 @@ dependencies {
implementation(projects.core)
implementation(projects.coroutineUtils)
implementation(projects.database)
implementation(projects.diScopes)
implementation(projects.metadataExtractor)
implementation(projects.model)
implementation(libs.accompanist.swiperefresh)
@ -76,10 +73,4 @@ dependencies {
implementation(libs.material.motion.core)
implementation(libs.material.motion.navigation)
implementation(libs.sqldelight.extensions.coroutines)
implementation(libs.tangle.viewmodel.api)
implementation(libs.tangle.viewmodel.compose) {
// https://github.com/RBusarow/Tangle/issues/558
exclude("androidx.compose.compiler")
}
implementation(libs.tangle.work.api)
}

View File

@ -1,23 +0,0 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android
import android.app.Application
import com.squareup.anvil.annotations.MergeComponent
import dagger.BindsInstance
import dagger.Component
import dev.msfjarvis.claw.injection.scopes.AppScope
import javax.inject.Singleton
@Singleton
@MergeComponent(AppScope::class)
interface AppComponent {
@Component.Factory
interface Factory {
fun create(@BindsInstance application: Application): AppComponent
}
}

View File

@ -7,24 +7,23 @@
package dev.msfjarvis.claw.android
import android.app.Application
import com.deliveryhero.whetstone.Whetstone
import com.deliveryhero.whetstone.app.ApplicationComponentOwner
import com.deliveryhero.whetstone.app.ContributesAppInjector
import dev.msfjarvis.claw.core.injection.AppPlugin
import dev.msfjarvis.claw.injection.Components
import dev.msfjarvis.claw.injection.scopes.AppScope
import javax.inject.Inject
import tangle.inject.TangleGraph
import tangle.inject.TangleScope
@TangleScope(AppScope::class)
class ClawApplication : Application() {
@ContributesAppInjector(generateAppComponent = true)
class ClawApplication : Application(), ApplicationComponentOwner {
override val applicationComponent by
lazy(LazyThreadSafetyMode.NONE) { GeneratedApplicationComponent.create(this) }
@Inject lateinit var plugins: Set<@JvmSuppressWildcards AppPlugin>
override fun onCreate() {
Whetstone.inject(this)
super.onCreate()
val component = DaggerAppComponent.factory().create(this)
Components.add(component)
TangleGraph.add(component)
TangleGraph.inject(this)
plugins.forEach { plugin -> plugin.apply(this) }
}
}

View File

@ -17,17 +17,16 @@ import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.NetworkType
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import com.deliveryhero.whetstone.Whetstone
import com.deliveryhero.whetstone.activity.ContributesActivityInjector
import dev.msfjarvis.claw.android.ui.LobstersApp
import dev.msfjarvis.claw.android.work.SavedPostUpdaterWorker
import dev.msfjarvis.claw.common.comments.HTMLConverter
import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
import dev.msfjarvis.claw.injection.scopes.AppScope
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import tangle.inject.TangleGraph
import tangle.inject.TangleScope
@TangleScope(AppScope::class)
@ContributesActivityInjector
class MainActivity : ComponentActivity() {
@Inject lateinit var urlLauncher: UrlLauncher
@ -36,8 +35,8 @@ class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
TangleGraph.inject(this)
installSplashScreen()
Whetstone.inject(this)
setContent {
LobstersApp(
urlLauncher = urlLauncher,

View File

@ -7,17 +7,18 @@
package dev.msfjarvis.claw.android.injection
import android.content.Context
import com.deliveryhero.whetstone.ForScope
import com.deliveryhero.whetstone.activity.ActivityScope
import com.squareup.anvil.annotations.ContributesTo
import dagger.Module
import dagger.Provides
import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
import dev.msfjarvis.claw.injection.scopes.AppScope
@Module
@ContributesTo(AppScope::class)
@ContributesTo(ActivityScope::class)
object UrlLauncherModule {
@Provides
fun provideUrlLauncher(context: Context): UrlLauncher {
fun provideUrlLauncher(@ForScope(ActivityScope::class) context: Context): UrlLauncher {
return UrlLauncher(context)
}
}

View File

@ -32,6 +32,7 @@ import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.navArgument
import androidx.navigation.navDeepLink
import androidx.paging.compose.collectAsLazyPagingItems
import com.deliveryhero.whetstone.compose.injectedViewModel
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import dev.msfjarvis.claw.android.R
import dev.msfjarvis.claw.android.ui.decorations.ClawNavigationBar
@ -53,7 +54,6 @@ import kotlinx.coroutines.launch
import soup.compose.material.motion.navigation.MaterialMotionNavHost
import soup.compose.material.motion.navigation.composable
import soup.compose.material.motion.navigation.rememberMaterialMotionNavController
import tangle.viewmodel.compose.tangleViewModel
@Suppress("ModifierMissing") // Top-level composable, will never have a modifier supplied.
@OptIn(ExperimentalMaterial3Api::class, ExperimentalAnimationApi::class)
@ -62,7 +62,7 @@ fun LobstersApp(
urlLauncher: UrlLauncher,
htmlConverter: HTMLConverter,
setWebUri: (String?) -> Unit,
viewModel: ClawViewModel = tangleViewModel(),
viewModel: ClawViewModel = injectedViewModel(),
) {
val systemUiController = rememberSystemUiController()
val hottestListState = rememberLazyListState()

View File

@ -10,6 +10,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import com.deliveryhero.whetstone.viewmodel.ContributesViewModel
import com.slack.eithernet.ApiResult.Failure
import com.slack.eithernet.ApiResult.Success
import dev.msfjarvis.claw.android.injection.IODispatcher
@ -19,15 +20,16 @@ import dev.msfjarvis.claw.api.LobstersApi
import dev.msfjarvis.claw.database.local.SavedPost
import java.io.IOException
import java.time.Month
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import tangle.viewmodel.VMInject
@ContributesViewModel
class ClawViewModel
@VMInject
@Inject
constructor(
private val api: LobstersApi,
private val savedPostsRepository: SavedPostsRepository,

View File

@ -9,17 +9,18 @@ package dev.msfjarvis.claw.android.work
import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.deliveryhero.whetstone.ForScope
import com.deliveryhero.whetstone.worker.ContributesWorker
import com.deliveryhero.whetstone.worker.WorkerScope
import com.slack.eithernet.ApiResult
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import dev.msfjarvis.claw.android.viewmodel.SavedPostsRepository
import dev.msfjarvis.claw.api.LobstersApi
import dev.msfjarvis.claw.common.posts.toDbModel
import javax.inject.Inject
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.supervisorScope
import tangle.work.TangleWorker
/**
* WorkManager-backed [CoroutineWorker] that gets all the posts from [SavedPostsRepository], fetches
@ -27,14 +28,14 @@ import tangle.work.TangleWorker
* saved posts that were saved before comment counts were added to be able to show a comment count
* and for new-enough posts that are still getting comments to have an accurate one.
*/
@TangleWorker
@ContributesWorker
class SavedPostUpdaterWorker
@AssistedInject
@Inject
constructor(
@ForScope(WorkerScope::class) appContext: Context,
workerParams: WorkerParameters,
private val savedPostsRepository: SavedPostsRepository,
private val lobstersApi: LobstersApi,
@Assisted appContext: Context,
@Assisted workerParams: WorkerParameters,
) : CoroutineWorker(appContext, workerParams) {
override suspend fun doWork(): Result {
val posts = savedPostsRepository.savedPosts.first()

View File

@ -1,34 +0,0 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.work
import android.app.Application
import android.util.Log
import androidx.work.Configuration
import androidx.work.WorkManager
import com.squareup.anvil.annotations.ContributesMultibinding
import dev.msfjarvis.claw.core.injection.AppPlugin
import dev.msfjarvis.claw.injection.scopes.AppScope
import javax.inject.Inject
import tangle.work.TangleWorkerFactory
@ContributesMultibinding(AppScope::class)
class WorkManagerPlugin
@Inject
constructor(
private val workerFactory: TangleWorkerFactory,
) : AppPlugin {
override fun apply(application: Application) {
WorkManager.initialize(
application,
Configuration.Builder()
.setWorkerFactory(workerFactory)
.setMinimumLoggingLevel(Log.DEBUG)
.build()
)
}
}

View File

@ -22,7 +22,6 @@ dependencies {
api(projects.model)
api(libs.retrofit)
api(libs.eithernet)
implementation(projects.diScopes)
implementation(libs.dagger)
implementation(libs.javax.inject)
testImplementation(testFixtures(libs.eithernet))

View File

@ -21,7 +21,6 @@ android { namespace = "dev.msfjarvis.claw.core" }
dependencies {
api(libs.kotlinx.serialization.json)
api(libs.okhttp.loggingInterceptor)
implementation(projects.diScopes)
implementation(libs.dagger)
implementation(libs.javax.inject)
implementation(libs.napier)

View File

@ -1,20 +0,0 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.core.injection
import android.app.Application
import android.content.Context
import com.squareup.anvil.annotations.ContributesTo
import dagger.Binds
import dagger.Module
import dev.msfjarvis.claw.injection.scopes.AppScope
@Module
@ContributesTo(AppScope::class)
interface ContextModule {
@get:Binds val Application.bindContext: Context
}

View File

@ -8,6 +8,7 @@ package dev.msfjarvis.claw.core.injection
import android.content.Context
import android.net.TrafficStats
import com.deliveryhero.whetstone.ForScope
import com.deliveryhero.whetstone.app.ApplicationScope
import com.squareup.anvil.annotations.ContributesTo
import dagger.Binds
@ -37,7 +38,7 @@ interface OkHttpModule {
private const val THREAD_STATS_TAG = 0x000090000
@Provides
fun provideCache(context: Context): Cache {
fun provideCache(@ForScope(ApplicationScope::class) context: Context): Cache {
return Cache(context.cacheDir, CACHE_SIZE_MB)
}

View File

@ -31,7 +31,6 @@ sqldelight {
dependencies {
implementation(libs.dagger)
implementation(projects.core)
implementation(projects.diScopes)
implementation(libs.sqldelight.androidDriver)
implementation(libs.sqldelight.primitiveAdapters)
testImplementation(libs.sqldelight.jvmDriver)

View File

@ -9,6 +9,7 @@ package dev.msfjarvis.claw.database.injection
import android.content.Context
import app.cash.sqldelight.adapter.primitive.IntColumnAdapter
import app.cash.sqldelight.driver.android.AndroidSqliteDriver
import com.deliveryhero.whetstone.ForScope
import com.deliveryhero.whetstone.app.ApplicationScope
import com.squareup.anvil.annotations.ContributesTo
import dagger.Module
@ -24,7 +25,7 @@ object DatabaseModule {
private const val LOBSTERS_DATABASE_NAME = "SavedPosts.db"
@Provides
fun provideDatabase(context: Context): LobstersDatabase {
fun provideDatabase(@ForScope(ApplicationScope::class) context: Context): LobstersDatabase {
val driver = AndroidSqliteDriver(LobstersDatabase.Schema, context, LOBSTERS_DATABASE_NAME)
return LobstersDatabase(driver, SavedPost.Adapter(IntColumnAdapter, TagsAdapter()))
}

View File

@ -2,7 +2,7 @@
<SmellBaseline>
<ManuallySuppressedIssues></ManuallySuppressedIssues>
<CurrentIssues>
<ID>LongMethod:LobstersApp.kt$@Suppress("ModifierMissing") // Top-level composable, will never have a modifier supplied. @OptIn(ExperimentalMaterial3Api::class, ExperimentalAnimationApi::class) @Composable fun LobstersApp( urlLauncher: UrlLauncher, htmlConverter: HTMLConverter, setWebUri: (String?) -&gt; Unit, viewModel: ClawViewModel = tangleViewModel(), )</ID>
<ID>LongMethod:LobstersApp.kt$@Suppress("ModifierMissing") // Top-level composable, will never have a modifier supplied. @OptIn(ExperimentalMaterial3Api::class, ExperimentalAnimationApi::class) @Composable fun LobstersApp( urlLauncher: UrlLauncher, htmlConverter: HTMLConverter, setWebUri: (String?) -&gt; Unit, viewModel: ClawViewModel = injectedViewModel(), )</ID>
<ID>LongParameterList:NetworkPosts.kt$( items: LazyPagingItems&lt;LobstersPost&gt;, listState: LazyListState, isPostSaved: suspend (SavedPost) -&gt; Boolean, reloadPosts: () -&gt; Unit, postActions: PostActions, modifier: Modifier = Modifier, )</ID>
</CurrentIssues>
</SmellBaseline>

View File

@ -1,18 +0,0 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
@file:Suppress("DSL_SCOPE_VIOLATION", "UnstableApiUsage")
plugins {
kotlin("jvm")
id("dev.msfjarvis.claw.kotlin-library")
alias(libs.plugins.anvil)
}
dependencies {
implementation(libs.dagger)
implementation(libs.javax.inject)
}

View File

@ -1,20 +0,0 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.injection
object Components {
@PublishedApi
@Suppress("ObjectPropertyName", "ObjectPropertyNaming")
internal val _components = mutableSetOf<Any>()
fun add(component: Any) {
_components.add(component)
}
inline fun <reified T> get(): T = _components.filterIsInstance<T>().single()
}

View File

@ -1,9 +0,0 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.injection.scopes
@Suppress("UnnecessaryAbstractClass") abstract class AppScope private constructor()

View File

@ -1,12 +0,0 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.injection.scopes
import javax.inject.Scope
import kotlin.reflect.KClass
@Scope @Retention(AnnotationRetention.RUNTIME) annotation class SingleIn(val clazz: KClass<*>)

View File

@ -15,7 +15,6 @@ retrofit = "2.9.0"
richtext = "0.15.0"
serialization = "1.4.1"
sqldelight = "2.0.0-alpha04"
tangle = "0.15.1"
whetstone = "0.3.0"
workmanager = "2.8.0-beta02"
@ -84,11 +83,6 @@ sqldelight-androidDriver = { module = "app.cash.sqldelight:android-driver", vers
sqldelight-extensions-coroutines = { module = "app.cash.sqldelight:coroutines-extensions-jvm", version.ref = "sqldelight" }
sqldelight-jvmDriver = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqldelight" }
sqldelight-primitiveAdapters = { module = "app.cash.sqldelight:primitive-adapters", version.ref = "sqldelight" }
tangle-viewmodel-api = { module = "com.rickbusarow.tangle:tangle-viewmodel-api", version.ref = "tangle" }
tangle-viewmodel-compiler = { module = "com.rickbusarow.tangle:tangle-viewmodel-compiler", version.ref = "tangle" }
tangle-viewmodel-compose = { module = "com.rickbusarow.tangle:tangle-viewmodel-compose", version.ref = "tangle" }
tangle-work-api = { module = "com.rickbusarow.tangle:tangle-work-api", version.ref = "tangle" }
tangle-work-compiler = { module = "com.rickbusarow.tangle:tangle-work-compiler", version.ref = "tangle" }
testparameterinjector = "com.google.testparameterinjector:test-parameter-injector:1.9"
whetstone = { module = "com.deliveryhero.whetstone:whetstone", version.ref = "whetstone" }

View File

@ -13,7 +13,6 @@ plugins {
dependencies {
api(libs.crux)
implementation(projects.diScopes)
implementation(projects.model)
implementation(libs.javax.inject)
implementation(libs.jsoup)

View File

@ -171,7 +171,6 @@ include(
"core",
"coroutine-utils",
"database",
"di-scopes",
"metadata-extractor",
"model",
)