Reduce overall build complexity

- Reduce the visibility of multiple Hilt `Module`s and implementations of public interfaces
- Correctly configure the visibility of dependencies:
  - `api` when it's part of it's public `api`
  - `implementation` when it's part of it's internal `implementation`
- Remove unnecessary dependencies in build.gradle.kts files
- Remove unnecessary dependencies provided by plugins
- Remove unnecessary applied plugins (i.e. roborazzi)
- Sort dependencies in `build.gradle.kts`
- Delete unused entries in `libs.versions.toml`
pull/1088/head
Simon Marquis 7 months ago
parent 63bba2ede7
commit f27a2e176e

@ -65,9 +65,10 @@ android {
}
dependencies {
implementation(libs.androidx.activity.compose)
implementation(projects.core.designsystem)
implementation(projects.core.ui)
implementation(libs.androidx.activity.compose)
}
dependencyGuard {

@ -25,6 +25,7 @@ plugins {
alias(libs.plugins.nowinandroid.android.application.firebase)
id("com.google.android.gms.oss-licenses-plugin")
alias(libs.plugins.baselineprofile)
alias(libs.plugins.roborazzi)
}
android {
@ -96,47 +97,41 @@ dependencies {
implementation(projects.core.data)
implementation(projects.core.model)
implementation(projects.core.analytics)
implementation(projects.sync.work)
androidTestImplementation(projects.core.testing)
androidTestImplementation(projects.core.datastoreTest)
androidTestImplementation(projects.core.dataTest)
androidTestImplementation(projects.core.network)
androidTestImplementation(libs.androidx.navigation.testing)
androidTestImplementation(libs.accompanist.testharness)
androidTestImplementation(kotlin("test"))
debugImplementation(libs.androidx.compose.ui.testManifest)
debugImplementation(projects.uiTestHiltManifest)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.core.splashscreen)
implementation(libs.androidx.compose.runtime)
implementation(libs.androidx.tracing.ktx)
implementation(libs.androidx.lifecycle.runtimeCompose)
implementation(libs.androidx.compose.runtime.tracing)
implementation(libs.androidx.compose.material3.windowSizeClass)
implementation(libs.androidx.hilt.navigation.compose)
implementation(libs.androidx.navigation.compose)
implementation(libs.androidx.window.manager)
implementation(libs.androidx.profileinstaller)
implementation(libs.kotlinx.coroutines.guava)
implementation(libs.coil.kt)
baselineProfile(project(":benchmarks"))
debugImplementation(libs.androidx.compose.ui.testManifest)
debugImplementation(projects.uiTestHiltManifest)
kspTest(libs.hilt.compiler)
// Core functions
testImplementation(projects.core.testing)
testImplementation(projects.core.datastoreTest)
testImplementation(projects.core.dataTest)
testImplementation(projects.core.network)
testImplementation(libs.androidx.navigation.testing)
testImplementation(projects.core.testing)
testImplementation(libs.accompanist.testharness)
testImplementation(libs.hilt.android.testing)
testImplementation(libs.work.testing)
testImplementation(kotlin("test"))
kspTest(libs.hilt.compiler)
testDemoImplementation(libs.robolectric)
testDemoImplementation(libs.roborazzi)
androidTestImplementation(projects.core.testing)
androidTestImplementation(projects.core.dataTest)
androidTestImplementation(projects.core.datastoreTest)
androidTestImplementation(libs.androidx.navigation.testing)
androidTestImplementation(libs.accompanist.testharness)
androidTestImplementation(libs.hilt.android.testing)
baselineProfile(projects.benchmarks)
}
baselineProfile {

@ -24,8 +24,6 @@ class AndroidApplicationComposeConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply("com.android.application")
// Screenshot Tests
pluginManager.apply("io.github.takahirom.roborazzi")
val extension = extensions.getByType<ApplicationExtension>()
configureAndroidCompose(extension)

@ -21,7 +21,6 @@ import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.kotlin
class AndroidFeatureConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
@ -39,27 +38,12 @@ class AndroidFeatureConventionPlugin : Plugin<Project> {
}
dependencies {
add("implementation", project(":core:model"))
add("implementation", project(":core:ui"))
add("implementation", project(":core:designsystem"))
add("implementation", project(":core:data"))
add("implementation", project(":core:common"))
add("implementation", project(":core:domain"))
add("implementation", project(":core:analytics"))
add("testImplementation", kotlin("test"))
add("testImplementation", project(":core:testing"))
add("androidTestImplementation", kotlin("test"))
add("androidTestImplementation", project(":core:testing"))
add("implementation", libs.findLibrary("coil.kt").get())
add("implementation", libs.findLibrary("coil.kt.compose").get())
add("implementation", libs.findLibrary("androidx.hilt.navigation.compose").get())
add("implementation", libs.findLibrary("androidx.lifecycle.runtimeCompose").get())
add("implementation", libs.findLibrary("androidx.lifecycle.viewModelCompose").get())
add("implementation", libs.findLibrary("kotlinx.coroutines.android").get())
}
}
}

@ -30,8 +30,6 @@ class AndroidHiltConventionPlugin : Plugin<Project> {
dependencies {
"implementation"(libs.findLibrary("hilt.android").get())
"ksp"(libs.findLibrary("hilt.compiler").get())
"kspAndroidTest"(libs.findLibrary("hilt.compiler").get())
"kspTest"(libs.findLibrary("hilt.compiler").get())
}
}

@ -26,8 +26,6 @@ class AndroidLibraryComposeConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply("com.android.library")
// Screenshot Tests
pluginManager.apply("io.github.takahirom.roborazzi")
val extension = extensions.getByType<LibraryExtension>()
configureAndroidCompose(extension)

@ -48,9 +48,6 @@ class AndroidLibraryConventionPlugin : Plugin<Project> {
}
dependencies {
add("testImplementation", kotlin("test"))
add("testImplementation", project(":core:testing"))
add("androidTestImplementation", kotlin("test"))
add("androidTestImplementation", project(":core:testing"))
}
}
}

@ -41,11 +41,6 @@ internal fun Project.configureAndroidCompose(
val bom = libs.findLibrary("androidx-compose-bom").get()
add("implementation", platform(bom))
add("androidTestImplementation", platform(bom))
// Add ComponentActivity to debug manifest
add("debugImplementation", libs.findLibrary("androidx.compose.ui.testManifest").get())
// Screenshot Tests on JVM
add("testImplementation", libs.findLibrary("robolectric").get())
add("testImplementation", libs.findLibrary("roborazzi").get())
}
testOptions {

@ -32,6 +32,7 @@ buildscript {
// Lists all plugins used throughout the project without applying them.
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.android.test) apply false
alias(libs.plugins.baselineprofile) apply false
alias(libs.plugins.kotlin.jvm) apply false

@ -24,9 +24,8 @@ android {
}
dependencies {
implementation(platform(libs.firebase.bom))
implementation(libs.androidx.compose.runtime)
implementation(libs.androidx.core.ktx)
implementation(libs.firebase.analytics)
implementation(libs.kotlinx.coroutines.android)
prodImplementation(platform(libs.firebase.bom))
prodImplementation(libs.firebase.analytics)
}

@ -23,7 +23,7 @@ import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
abstract class AnalyticsModule {
internal abstract class AnalyticsModule {
@Binds
abstract fun bindsAnalyticsHelper(analyticsHelperImpl: StubAnalyticsHelper): AnalyticsHelper
}

@ -27,7 +27,7 @@ private const val TAG = "StubAnalyticsHelper"
* analytics events should be sent to a backend.
*/
@Singleton
class StubAnalyticsHelper @Inject constructor() : AnalyticsHelper {
internal class StubAnalyticsHelper @Inject constructor() : AnalyticsHelper {
override fun logEvent(event: AnalyticsEvent) {
Log.d(TAG, "Received analytics event: $event")
}

@ -28,7 +28,7 @@ import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
abstract class AnalyticsModule {
internal abstract class AnalyticsModule {
@Binds
abstract fun bindsAnalyticsHelper(analyticsHelperImpl: FirebaseAnalyticsHelper): AnalyticsHelper

@ -23,7 +23,7 @@ import javax.inject.Inject
/**
* Implementation of `AnalyticsHelper` which logs events to a Firebase backend.
*/
class FirebaseAnalyticsHelper @Inject constructor(
internal class FirebaseAnalyticsHelper @Inject constructor(
private val firebaseAnalytics: FirebaseAnalytics,
) : AnalyticsHelper {

@ -24,6 +24,6 @@ android {
}
dependencies {
implementation(libs.kotlinx.coroutines.android)
testImplementation(projects.core.testing)
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.turbine)
}

@ -34,7 +34,7 @@ annotation class ApplicationScope
@Module
@InstallIn(SingletonComponent::class)
object CoroutineScopesModule {
internal object CoroutineScopesModule {
@Provides
@Singleton
@ApplicationScope

@ -24,6 +24,6 @@ android {
dependencies {
api(projects.core.data)
implementation(projects.core.testing)
implementation(projects.core.common)
implementation(libs.hilt.android.testing)
}

@ -31,18 +31,16 @@ android {
}
dependencies {
api(projects.core.common)
api(projects.core.database)
api(projects.core.datastore)
api(projects.core.network)
implementation(projects.core.analytics)
implementation(projects.core.common)
implementation(projects.core.database)
implementation(projects.core.datastore)
implementation(projects.core.model)
implementation(projects.core.network)
implementation(projects.core.notifications)
implementation(libs.androidx.core.ktx)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.datetime)
implementation(libs.kotlinx.serialization.json)
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.kotlinx.serialization.json)
testImplementation(projects.core.datastoreTest)
testImplementation(projects.core.testing)
}

@ -35,35 +35,35 @@ import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
interface DataModule {
abstract class DataModule {
@Binds
fun bindsTopicRepository(
internal abstract fun bindsTopicRepository(
topicsRepository: OfflineFirstTopicsRepository,
): TopicsRepository
@Binds
fun bindsNewsResourceRepository(
internal abstract fun bindsNewsResourceRepository(
newsRepository: OfflineFirstNewsRepository,
): NewsRepository
@Binds
fun bindsUserDataRepository(
internal abstract fun bindsUserDataRepository(
userDataRepository: OfflineFirstUserDataRepository,
): UserDataRepository
@Binds
fun bindsRecentSearchRepository(
internal abstract fun bindsRecentSearchRepository(
recentSearchRepository: DefaultRecentSearchRepository,
): RecentSearchRepository
@Binds
fun bindsSearchContentsRepository(
internal abstract fun bindsSearchContentsRepository(
searchContentsRepository: DefaultSearchContentsRepository,
): SearchContentsRepository
@Binds
fun bindsNetworkMonitor(
internal abstract fun bindsNetworkMonitor(
networkMonitor: ConnectivityManagerNetworkMonitor,
): NetworkMonitor
}

@ -25,7 +25,7 @@ import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
interface UserNewsResourceRepositoryModule {
internal interface UserNewsResourceRepositoryModule {
@Binds
fun bindsUserNewsResourceRepository(
userDataRepository: CompositeUserNewsResourceRepository,

@ -20,7 +20,7 @@ import com.google.samples.apps.nowinandroid.core.analytics.AnalyticsEvent
import com.google.samples.apps.nowinandroid.core.analytics.AnalyticsEvent.Param
import com.google.samples.apps.nowinandroid.core.analytics.AnalyticsHelper
fun AnalyticsHelper.logNewsResourceBookmarkToggled(newsResourceId: String, isBookmarked: Boolean) {
internal fun AnalyticsHelper.logNewsResourceBookmarkToggled(newsResourceId: String, isBookmarked: Boolean) {
val eventType = if (isBookmarked) "news_resource_saved" else "news_resource_unsaved"
val paramKey = if (isBookmarked) "saved_news_resource_id" else "unsaved_news_resource_id"
logEvent(
@ -33,7 +33,7 @@ fun AnalyticsHelper.logNewsResourceBookmarkToggled(newsResourceId: String, isBoo
)
}
fun AnalyticsHelper.logTopicFollowToggled(followedTopicId: String, isFollowed: Boolean) {
internal fun AnalyticsHelper.logTopicFollowToggled(followedTopicId: String, isFollowed: Boolean) {
val eventType = if (isFollowed) "topic_followed" else "topic_unfollowed"
val paramKey = if (isFollowed) "followed_topic_id" else "unfollowed_topic_id"
logEvent(
@ -46,7 +46,7 @@ fun AnalyticsHelper.logTopicFollowToggled(followedTopicId: String, isFollowed: B
)
}
fun AnalyticsHelper.logThemeChanged(themeName: String) =
internal fun AnalyticsHelper.logThemeChanged(themeName: String) =
logEvent(
AnalyticsEvent(
type = "theme_changed",
@ -56,7 +56,7 @@ fun AnalyticsHelper.logThemeChanged(themeName: String) =
),
)
fun AnalyticsHelper.logDarkThemeConfigChanged(darkThemeConfigName: String) =
internal fun AnalyticsHelper.logDarkThemeConfigChanged(darkThemeConfigName: String) =
logEvent(
AnalyticsEvent(
type = "dark_theme_config_changed",
@ -66,7 +66,7 @@ fun AnalyticsHelper.logDarkThemeConfigChanged(darkThemeConfigName: String) =
),
)
fun AnalyticsHelper.logDynamicColorPreferenceChanged(useDynamicColor: Boolean) =
internal fun AnalyticsHelper.logDynamicColorPreferenceChanged(useDynamicColor: Boolean) =
logEvent(
AnalyticsEvent(
type = "dynamic_color_preference_changed",
@ -76,7 +76,7 @@ fun AnalyticsHelper.logDynamicColorPreferenceChanged(useDynamicColor: Boolean) =
),
)
fun AnalyticsHelper.logOnboardingStateChanged(shouldHideOnboarding: Boolean) {
internal fun AnalyticsHelper.logOnboardingStateChanged(shouldHideOnboarding: Boolean) {
val eventType = if (shouldHideOnboarding) "onboarding_complete" else "onboarding_reset"
logEvent(
AnalyticsEvent(type = eventType),

@ -25,7 +25,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.datetime.Clock
import javax.inject.Inject
class DefaultRecentSearchRepository @Inject constructor(
internal class DefaultRecentSearchRepository @Inject constructor(
private val recentSearchQueryDao: RecentSearchQueryDao,
) : RecentSearchRepository {
override suspend fun insertOrReplaceRecentSearch(searchQuery: String) {

@ -36,7 +36,7 @@ import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.withContext
import javax.inject.Inject
class DefaultSearchContentsRepository @Inject constructor(
internal class DefaultSearchContentsRepository @Inject constructor(
private val newsResourceDao: NewsResourceDao,
private val newsResourceFtsDao: NewsResourceFtsDao,
private val topicDao: TopicDao,

@ -45,7 +45,7 @@ private const val SYNC_BATCH_SIZE = 40
* Disk storage backed implementation of the [NewsRepository].
* Reads are exclusively from local storage to support offline access.
*/
class OfflineFirstNewsRepository @Inject constructor(
internal class OfflineFirstNewsRepository @Inject constructor(
private val niaPreferencesDataSource: NiaPreferencesDataSource,
private val newsResourceDao: NewsResourceDao,
private val topicDao: TopicDao,

@ -34,7 +34,7 @@ import javax.inject.Inject
* Disk storage backed implementation of the [TopicsRepository].
* Reads are exclusively from local storage to support offline access.
*/
class OfflineFirstTopicsRepository @Inject constructor(
internal class OfflineFirstTopicsRepository @Inject constructor(
private val topicDao: TopicDao,
private val network: NiaNetworkDataSource,
) : TopicsRepository {

@ -25,7 +25,7 @@ import com.google.samples.apps.nowinandroid.core.model.data.UserData
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
class OfflineFirstUserDataRepository @Inject constructor(
internal class OfflineFirstUserDataRepository @Inject constructor(
private val niaPreferencesDataSource: NiaPreferencesDataSource,
private val analyticsHelper: AnalyticsHelper,
) : UserDataRepository {

@ -33,7 +33,7 @@ import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.conflate
import javax.inject.Inject
class ConnectivityManagerNetworkMonitor @Inject constructor(
internal class ConnectivityManagerNetworkMonitor @Inject constructor(
@ApplicationContext private val context: Context,
) : NetworkMonitor {
override val isOnline: Flow<Boolean> = callbackFlow {

@ -30,9 +30,8 @@ android {
}
dependencies {
implementation(projects.core.model)
api(projects.core.model)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.datetime)
androidTestImplementation(projects.core.testing)

@ -28,7 +28,7 @@ import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
object DaosModule {
internal object DaosModule {
@Provides
fun providesTopicsDao(
database: NiaDatabase,

@ -28,7 +28,7 @@ import androidx.room.migration.AutoMigrationSpec
* from and Y is the schema version you're migrating to. The class should implement
* `AutoMigrationSpec`.
*/
object DatabaseMigrations {
internal object DatabaseMigrations {
@RenameColumn(
tableName = "topics",

@ -27,7 +27,7 @@ import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {
internal object DatabaseModule {
@Provides
@Singleton
fun providesNiaDatabase(

@ -63,7 +63,7 @@ import com.google.samples.apps.nowinandroid.core.database.util.InstantConverter
@TypeConverters(
InstantConverter::class,
)
abstract class NiaDatabase : RoomDatabase() {
internal abstract class NiaDatabase : RoomDatabase() {
abstract fun topicDao(): TopicDao
abstract fun newsResourceDao(): NewsResourceDao
abstract fun topicFtsDao(): TopicFtsDao

@ -19,7 +19,7 @@ package com.google.samples.apps.nowinandroid.core.database.util
import androidx.room.TypeConverter
import kotlinx.datetime.Instant
class InstantConverter {
internal class InstantConverter {
@TypeConverter
fun longToInstant(value: Long?): Instant? =
value?.let(Instant::fromEpochMilliseconds)

@ -51,5 +51,5 @@ androidComponents.beforeVariants {
}
dependencies {
implementation(libs.protobuf.kotlin.lite)
api(libs.protobuf.kotlin.lite)
}

@ -23,10 +23,7 @@ android {
}
dependencies {
api(projects.core.datastore)
api(libs.androidx.dataStore.core)
implementation(libs.protobuf.kotlin.lite)
implementation(libs.hilt.android.testing)
implementation(projects.core.common)
implementation(projects.core.testing)
implementation(projects.core.datastore)
}

@ -35,7 +35,7 @@ import javax.inject.Singleton
components = [SingletonComponent::class],
replaces = [DataStoreModule::class],
)
object TestDataStoreModule {
internal object TestDataStoreModule {
@Provides
@Singleton

@ -33,13 +33,12 @@ android {
}
dependencies {
api(libs.androidx.dataStore.core)
api(projects.core.datastoreProto)
api(projects.core.model)
implementation(projects.core.common)
implementation(projects.core.model)
implementation(libs.androidx.dataStore.core)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.protobuf.kotlin.lite)
testImplementation(projects.core.datastoreTest)
testImplementation(projects.core.testing)
testImplementation(libs.kotlinx.coroutines.test)
}

@ -21,7 +21,7 @@ import androidx.datastore.core.DataMigration
/**
* Migrates saved ids from [Int] to [String] types
*/
object IntToStringIdsMigration : DataMigration<UserPreferences> {
internal object IntToStringIdsMigration : DataMigration<UserPreferences> {
override suspend fun cleanUp() = Unit

@ -21,7 +21,7 @@ import androidx.datastore.core.DataMigration
/**
* Migrates from using lists to maps for user data.
*/
object ListToMapMigration : DataMigration<UserPreferences> {
internal object ListToMapMigration : DataMigration<UserPreferences> {
override suspend fun cleanUp() = Unit

@ -41,7 +41,7 @@ object DataStoreModule {
@Provides
@Singleton
fun providesUserPreferencesDataStore(
internal fun providesUserPreferencesDataStore(
@ApplicationContext context: Context,
@Dispatcher(IO) ioDispatcher: CoroutineDispatcher,
@ApplicationScope scope: CoroutineScope,

@ -17,6 +17,7 @@ plugins {
alias(libs.plugins.nowinandroid.android.library)
alias(libs.plugins.nowinandroid.android.library.compose)
alias(libs.plugins.nowinandroid.android.library.jacoco)
alias(libs.plugins.roborazzi)
}
android {
@ -39,8 +40,15 @@ dependencies {
debugApi(libs.androidx.compose.ui.tooling)
implementation(libs.androidx.core.ktx)
implementation(libs.coil.kt.compose)
testImplementation(libs.androidx.compose.ui.test)
testImplementation(libs.accompanist.testharness)
testImplementation(libs.hilt.android.testing)
testImplementation(libs.robolectric)
testImplementation(libs.roborazzi)
testImplementation(projects.core.testing)
androidTestImplementation(libs.androidx.compose.ui.test)
androidTestImplementation(projects.core.testing)
}

@ -24,13 +24,10 @@ android {
}
dependencies {
implementation(projects.core.data)
implementation(projects.core.model)
implementation(libs.hilt.android)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.datetime)
api(projects.core.data)
api(projects.core.model)
ksp(libs.hilt.compiler)
implementation(libs.javax.inject)
testImplementation(projects.core.testing)
}

@ -19,5 +19,5 @@ plugins {
}
dependencies {
implementation(libs.kotlinx.datetime)
api(libs.kotlinx.datetime)
}

@ -39,16 +39,16 @@ secrets {
}
dependencies {
implementation(projects.core.common)
implementation(projects.core.model)
api(libs.kotlinx.datetime)
api(projects.core.common)
api(projects.core.model)
implementation(libs.coil.kt)
implementation(libs.coil.kt.svg)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.datetime)
implementation(libs.kotlinx.serialization.json)
implementation(libs.okhttp.logging)
implementation(libs.retrofit.core)
implementation(libs.retrofit.kotlin.serialization)
testImplementation(projects.core.testing)
testImplementation(libs.kotlinx.coroutines.test)
}

@ -25,7 +25,7 @@ import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
interface FlavoredNetworkModule {
internal interface FlavoredNetworkModule {
@Binds
fun binds(impl: FakeNiaNetworkDataSource): NiaNetworkDataSource

@ -35,7 +35,7 @@ import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
internal object NetworkModule {
@Provides
@Singleton

@ -71,7 +71,7 @@ private data class NetworkResponse<T>(
* [Retrofit] backed [NiaNetworkDataSource]
*/
@Singleton
class RetrofitNiaNetwork @Inject constructor(
internal class RetrofitNiaNetwork @Inject constructor(
networkJson: Json,
okhttpCallFactory: Call.Factory,
) : NiaNetworkDataSource {

@ -25,7 +25,7 @@ import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
interface FlavoredNetworkModule {
internal interface FlavoredNetworkModule {
@Binds
fun binds(impl: RetrofitNiaNetwork): NiaNetworkDataSource

@ -15,7 +15,6 @@
*/
plugins {
alias(libs.plugins.nowinandroid.android.library)
alias(libs.plugins.nowinandroid.android.library.compose)
alias(libs.plugins.nowinandroid.android.hilt)
}
@ -24,14 +23,10 @@ android {
}
dependencies {
implementation(projects.core.common)
implementation(projects.core.model)
api(projects.core.model)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.androidx.browser)
implementation(libs.androidx.compose.runtime)
implementation(libs.androidx.core.ktx)
implementation(projects.core.common)
implementation(platform(libs.firebase.bom))
implementation(libs.firebase.cloud.messaging)
compileOnly(platform(libs.androidx.compose.bom))
compileOnly(libs.androidx.compose.runtime)
}

@ -23,7 +23,7 @@ import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
abstract class NotificationsModule {
internal abstract class NotificationsModule {
@Binds
abstract fun bindNotifier(
notifier: NoOpNotifier,

@ -22,6 +22,6 @@ import javax.inject.Inject
/**
* Implementation of [Notifier] which does nothing. Useful for tests and previews.
*/
class NoOpNotifier @Inject constructor() : Notifier {
internal class NoOpNotifier @Inject constructor() : Notifier {
override fun postNewsNotifications(newsResources: List<NewsResource>) = Unit
}

@ -50,7 +50,7 @@ private const val FOR_YOU_PATH = "foryou"
* Implementation of [Notifier] that displays notifications in the system tray.
*/
@Singleton
class SystemTrayNotifier @Inject constructor(
internal class SystemTrayNotifier @Inject constructor(
@ApplicationContext private val context: Context,
) : Notifier {

@ -23,7 +23,7 @@ import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
abstract class NotificationsModule {
internal abstract class NotificationsModule {
@Binds
abstract fun bindNotifier(
notifier: SystemTrayNotifier,

@ -24,28 +24,23 @@ android {
}
dependencies {
api(libs.accompanist.testharness)
api(libs.androidx.activity.compose)
api(kotlin("test"))
api(libs.androidx.compose.ui.test)
api(libs.androidx.test.core)
api(libs.androidx.test.espresso.core)
api(libs.androidx.test.rules)
api(libs.androidx.test.runner)
api(libs.hilt.android.testing)
api(libs.junit4)
api(libs.kotlinx.coroutines.test)
api(libs.roborazzi)
api(libs.robolectric.shadows)
api(libs.turbine)
api(projects.core.analytics)
api(projects.core.data)
api(projects.core.model)
api(projects.core.notifications)
debugApi(libs.androidx.compose.ui.testManifest)
implementation(libs.accompanist.testharness)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.test.rules)
implementation(libs.hilt.android.testing)
implementation(libs.kotlinx.coroutines.test)
implementation(libs.kotlinx.datetime)
implementation(libs.robolectric.shadows)
implementation(projects.core.common)
implementation(projects.core.data)
implementation(projects.core.designsystem)
implementation(projects.core.domain)
implementation(projects.core.model)
implementation(projects.core.notifications)
implementation(projects.core.analytics)
implementation(libs.kotlinx.datetime)
}

@ -26,7 +26,7 @@ import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object TestDispatcherModule {
internal object TestDispatcherModule {
@Provides
@Singleton
fun providesTestDispatcher(): TestDispatcher = UnconfinedTestDispatcher()

@ -32,7 +32,7 @@ import kotlinx.coroutines.test.TestDispatcher
components = [SingletonComponent::class],
replaces = [DispatchersModule::class],
)
object TestDispatchersModule {
internal object TestDispatchersModule {
@Provides
@Dispatcher(IO)
fun providesIODispatcher(testDispatcher: TestDispatcher): CoroutineDispatcher = testDispatcher

@ -27,29 +27,14 @@ android {
}
dependencies {
api(libs.androidx.compose.foundation)
api(libs.androidx.compose.foundation.layout)
api(libs.androidx.compose.material.iconsExtended)
api(libs.androidx.compose.material3)
api(libs.androidx.compose.runtime)
api(libs.androidx.compose.runtime.livedata)
api(libs.androidx.compose.ui.tooling.preview)
api(libs.androidx.compose.ui.util)
api(libs.androidx.metrics)
api(libs.androidx.tracing.ktx)
api(projects.core.analytics)
api(projects.core.designsystem)
api(projects.core.model)
debugApi(libs.androidx.compose.ui.tooling)
implementation(projects.core.analytics)
implementation(projects.core.designsystem)
implementation(projects.core.domain)
implementation(projects.core.model)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.browser)
implementation(libs.androidx.core.ktx)
implementation(libs.coil.kt)
implementation(libs.coil.kt.compose)
implementation(libs.kotlinx.datetime)
androidTestImplementation(projects.core.testing)
}

@ -25,5 +25,9 @@ android {
}
dependencies {
implementation(libs.androidx.compose.material3.windowSizeClass)
implementation(projects.core.data)
testImplementation(projects.core.testing)
androidTestImplementation(projects.core.testing)
}

@ -25,7 +25,13 @@ android {
}
dependencies {
implementation(libs.kotlinx.datetime)
implementation(libs.androidx.activity.compose)
implementation(libs.accompanist.permissions)
implementation(projects.core.data)
implementation(projects.core.domain)
testImplementation(libs.hilt.android.testing)
testImplementation(libs.robolectric)
testImplementation(projects.core.testing)
androidTestImplementation(projects.core.testing)
}

@ -22,3 +22,12 @@ plugins {
android {
namespace = "com.google.samples.apps.nowinandroid.feature.interests"
}
dependencies {
implementation(projects.core.data)
implementation(projects.core.domain)
testImplementation(projects.core.testing)
androidTestImplementation(projects.core.testing)
}

@ -25,9 +25,14 @@ android {
}
dependencies {
implementation(projects.core.data)
implementation(projects.core.domain)
implementation(projects.feature.bookmarks)
implementation(projects.feature.foryou)
implementation(projects.feature.interests)
implementation(libs.kotlinx.datetime)
testImplementation(projects.core.testing)
androidTestImplementation(projects.core.testing)
}

@ -26,7 +26,10 @@ android {
dependencies {
implementation(libs.androidx.appcompat)
implementation(libs.google.oss.licenses) {
exclude(group = "androidx.appcompat")
}
implementation(libs.google.oss.licenses)
implementation(projects.core.data)
testImplementation(projects.core.testing)
androidTestImplementation(projects.core.testing)
}

@ -25,5 +25,9 @@ android {
}
dependencies {
implementation(libs.kotlinx.datetime)
implementation(projects.core.data)
testImplementation(projects.core.testing)
androidTestImplementation(projects.core.testing)
}

@ -9,26 +9,22 @@ androidxAppCompat = "1.6.1"
androidxBrowser = "1.6.0"
androidxComposeBom = "2023.10.01"
androidxComposeCompiler = "1.5.3"
androidxComposeRuntimeTracing = "1.0.0-alpha03"
androidxCore = "1.12.0"
androidxCoreSplashscreen = "1.0.1"
androidxDataStore = "1.0.0"
androidxEspresso = "3.5.1"
androidxHiltNavigationCompose = "1.0.0"
androidxJunit = "1.1.5"
androidxLifecycle = "2.6.2"
androidxMacroBenchmark = "1.2.0"
androidxMetrics = "1.0.0-alpha04"
androidxNavigation = "2.7.4"
androidxProfileinstaller = "1.3.1"
androidxStartup = "1.1.1"
androidxTestCore = "1.5.0"
androidxTestExt = "1.1.5"
androidxTestRules = "1.5.0"
androidxTestRunner = "1.5.2"
androidxTracing = "1.1.0"
androidxUiAutomator = "2.2.0"
androidxWindowManager = "1.1.0"
androidxWork = "2.9.0-rc01"
coil = "2.4.0"
dependencyGuard = "0.4.3"
@ -41,7 +37,6 @@ googleOssPlugin = "0.10.6"
hilt = "2.48.1"
hiltExt = "1.1.0"
jacoco = "0.8.7"
junit4 = "4.13.2"
kotlin = "1.9.10"
kotlinxCoroutines = "1.7.3"
kotlinxDatetime = "0.4.1"
@ -68,15 +63,12 @@ androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version
androidx-benchmark-macro = { group = "androidx.benchmark", name = "benchmark-macro-junit4", version.ref = "androidxMacroBenchmark" }
androidx-browser = { group = "androidx.browser", name = "browser", version.ref = "androidxBrowser" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "androidxComposeBom" }
androidx-compose-compiler = { group = "androidx.compose.compiler", name = "compiler", version.ref = "androidxComposeCompiler" }
androidx-compose-foundation = { group = "androidx.compose.foundation", name = "foundation" }
androidx-compose-foundation-layout = { group = "androidx.compose.foundation", name = "foundation-layout" }
androidx-compose-material-iconsExtended = { group = "androidx.compose.material", name = "material-icons-extended" }
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-compose-material3-windowSizeClass = { group = "androidx.compose.material3", name = "material3-window-size-class" }
androidx-compose-runtime = { group = "androidx.compose.runtime", name = "runtime" }
androidx-compose-runtime-livedata = { group = "androidx.compose.runtime", name = "runtime-livedata" }
androidx-compose-runtime-tracing = { group = "androidx.compose.runtime", name = "runtime-tracing", version.ref = "androidxComposeRuntimeTracing" }
androidx-compose-ui-test = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-compose-ui-testManifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
@ -86,7 +78,6 @@ androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref =
androidx-core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "androidxCoreSplashscreen" }
androidx-dataStore-core = { group = "androidx.datastore", name = "datastore", version.ref = "androidxDataStore" }
androidx-hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "androidxHiltNavigationCompose" }
androidx-lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "androidxLifecycle" }
androidx-lifecycle-runtimeCompose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "androidxLifecycle" }
androidx-lifecycle-viewModelCompose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "androidxLifecycle" }
androidx-metrics = { group = "androidx.metrics", name = "metrics-performance", version.ref = "androidxMetrics" }
@ -100,7 +91,6 @@ androidx-test-rules = { group = "androidx.test", name = "rules", version.ref = "
androidx-test-runner = { group = "androidx.test", name = "runner", version.ref = "androidxTestRunner" }
androidx-test-uiautomator = { group = "androidx.test.uiautomator", name = "uiautomator", version.ref = "androidxUiAutomator" }
androidx-tracing-ktx = { group = "androidx.tracing", name = "tracing-ktx", version.ref = "androidxTracing" }
androidx-window-manager = { module = "androidx.window:window", version.ref = "androidxWindowManager" }
androidx-work-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "androidxWork" }
androidx-work-testing = { group = "androidx.work", name = "work-testing", version.ref = "androidxWork" }
coil-kt = { group = "io.coil-kt", name = "coil", version.ref = "coil" }
@ -111,7 +101,6 @@ firebase-bom = { group = "com.google.firebase", name = "firebase-bom", version.r
firebase-cloud-messaging = { group = "com.google.firebase", name = "firebase-messaging-ktx" }
firebase-crashlytics = { group = "com.google.firebase", name = "firebase-crashlytics-ktx" }
firebase-performance = { group = "com.google.firebase", name = "firebase-perf-ktx" }
firebase-performance-gradle = { group = "com.google.firebase", name = "perf-plugin", version.ref = "firebasePerfPlugin" }
google-oss-licenses = { group = "com.google.android.gms", name = "play-services-oss-licenses", version.ref = "googleOss" }
google-oss-licenses-plugin = { group = "com.google.android.gms", name = "oss-licenses-plugin", version.ref = "googleOssPlugin" }
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
@ -119,9 +108,8 @@ hilt-android-testing = { group = "com.google.dagger", name = "hilt-android-testi
hilt-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" }
hilt-ext-compiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "hiltExt" }
hilt-ext-work = { group = "androidx.hilt", name = "hilt-work", version.ref = "hiltExt" }
junit4 = { group = "junit", name = "junit", version.ref = "junit4" }
javax-inject = { module = "javax.inject:javax.inject", version = "1" }
kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", version.ref = "kotlin" }
kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "kotlinxCoroutines" }
kotlinx-coroutines-guava = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-guava", version.ref = "kotlinxCoroutines" }
kotlinx-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "kotlinxCoroutines" }
kotlinx-datetime = { group = "org.jetbrains.kotlinx", name = "kotlinx-datetime", version.ref = "kotlinxDatetime" }
@ -145,7 +133,6 @@ turbine = { group = "app.cash.turbine", name = "turbine", version.ref = "turbine
# Dependencies of the included build-logic
android-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" }
android-tools-common = { group = "com.android.tools", name = "common", version.ref = "androidTools" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidxJunit" }
firebase-crashlytics-gradlePlugin = { group = "com.google.firebase", name = "firebase-crashlytics-gradle", version.ref = "firebaseCrashlyticsPlugin" }
firebase-performance-gradlePlugin = { group = "com.google.firebase", name = "perf-plugin", version.ref = "firebasePerfPlugin" }
kotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }

@ -23,7 +23,7 @@ android {
}
dependencies {
api(projects.sync.work)
implementation(libs.hilt.android.testing)
implementation(projects.core.data)
implementation(projects.core.testing)
implementation(projects.sync.work)
}

@ -21,7 +21,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import javax.inject.Inject
class NeverSyncingSyncManager @Inject constructor() : SyncManager {
internal class NeverSyncingSyncManager @Inject constructor() : SyncManager {
override val isSyncing: Flow<Boolean> = flowOf(false)
override fun requestSync() = Unit
}

@ -28,7 +28,7 @@ import dagger.hilt.testing.TestInstallIn
components = [SingletonComponent::class],
replaces = [SyncModule::class],
)
interface TestSyncModule {
internal interface TestSyncModule {
@Binds
fun bindsSyncStatusMonitor(
syncStatusMonitor: NeverSyncingSyncManager,

@ -27,23 +27,19 @@ android {
}
dependencies {
implementation(projects.core.analytics)
implementation(projects.core.common)
implementation(projects.core.data)
implementation(projects.core.datastore)
implementation(projects.core.model)
implementation(libs.androidx.lifecycle.livedata.ktx)
ksp(libs.hilt.ext.compiler)
implementation(libs.androidx.tracing.ktx)
implementation(libs.androidx.work.ktx)
implementation(libs.hilt.ext.work)
implementation(libs.kotlinx.coroutines.android)
implementation(projects.core.analytics)
implementation(projects.core.data)
prodImplementation(libs.firebase.cloud.messaging)
prodImplementation(platform(libs.firebase.bom))
ksp(libs.hilt.ext.compiler)
testImplementation(projects.core.testing)
androidTestImplementation(projects.core.testing)
androidTestImplementation(libs.androidx.work.testing)
androidTestImplementation(libs.hilt.android.testing)
androidTestImplementation(libs.kotlinx.coroutines.guava)
androidTestImplementation(projects.core.testing)
}

@ -27,14 +27,14 @@ import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
interface SyncModule {
abstract class SyncModule {
@Binds
fun bindsSyncStatusMonitor(
internal abstract fun bindsSyncStatusMonitor(
syncStatusMonitor: WorkManagerSyncManager,
): SyncManager
@Binds
fun bindsSyncSubscriber(
internal abstract fun bindsSyncSubscriber(
syncSubscriber: StubSyncSubscriber,
): SyncSubscriber
}

@ -24,7 +24,7 @@ private const val TAG = "StubSyncSubscriber"
/**
* Stub implementation of [SyncSubscriber]
*/
class StubSyncSubscriber @Inject constructor() : SyncSubscriber {
internal class StubSyncSubscriber @Inject constructor() : SyncSubscriber {
override suspend fun subscribe() {
Log.d(TAG, "Subscribing to sync")
}

@ -33,7 +33,7 @@ import javax.inject.Inject
/**
* [SyncManager] backed by [WorkInfo] from [WorkManager]
*/
class WorkManagerSyncManager @Inject constructor(
internal class WorkManagerSyncManager @Inject constructor(
@ApplicationContext private val context: Context,
) : SyncManager {
override val isSyncing: Flow<Boolean> =

@ -19,12 +19,12 @@ package com.google.samples.apps.nowinandroid.sync.workers
import com.google.samples.apps.nowinandroid.core.analytics.AnalyticsEvent
import com.google.samples.apps.nowinandroid.core.analytics.AnalyticsHelper
fun AnalyticsHelper.logSyncStarted() =
internal fun AnalyticsHelper.logSyncStarted() =
logEvent(
AnalyticsEvent(type = "network_sync_started"),
)
fun AnalyticsHelper.logSyncFinished(syncedSuccessfully: Boolean) {
internal fun AnalyticsHelper.logSyncFinished(syncedSuccessfully: Boolean) {
val eventType = if (syncedSuccessfully) "network_sync_successful" else "network_sync_failed"
logEvent(
AnalyticsEvent(type = eventType),

@ -48,7 +48,7 @@ import kotlinx.coroutines.withContext
* sync functionality.
*/
@HiltWorker
class SyncWorker @AssistedInject constructor(
internal class SyncWorker @AssistedInject constructor(
@Assisted private val appContext: Context,
@Assisted workerParams: WorkerParameters,
private val niaPreferences: NiaPreferencesDataSource,

@ -32,20 +32,20 @@ import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
interface SyncModule {
abstract class SyncModule {
@Binds
fun bindsSyncStatusMonitor(
internal abstract fun bindsSyncStatusMonitor(
syncStatusMonitor: WorkManagerSyncManager,
): SyncManager
@Binds
fun bindsSyncSubscriber(
internal abstract fun bindsSyncSubscriber(
syncSubscriber: FirebaseSyncSubscriber,
): SyncSubscriber
companion object {
@Provides
@Singleton
fun provideFirebaseMessaging(): FirebaseMessaging = Firebase.messaging
internal fun provideFirebaseMessaging(): FirebaseMessaging = Firebase.messaging
}
}

@ -25,7 +25,7 @@ import javax.inject.Inject
private const val SYNC_TOPIC_SENDER = "/topics/sync"
@AndroidEntryPoint
class SyncNotificationsService : FirebaseMessagingService() {
internal class SyncNotificationsService : FirebaseMessagingService() {
@Inject
lateinit var syncManager: SyncManager

@ -24,7 +24,7 @@ import javax.inject.Inject
/**
* Implementation of [SyncSubscriber] that subscribes to the FCM [SYNC_TOPIC]
*/
class FirebaseSyncSubscriber @Inject constructor(
internal class FirebaseSyncSubscriber @Inject constructor(
private val firebaseMessaging: FirebaseMessaging,
) : SyncSubscriber {
override suspend fun subscribe() {

Loading…
Cancel
Save