diff --git a/.github/workflows/github-actions b/.github/workflows/github-actions new file mode 100644 index 00000000..30d46986 --- /dev/null +++ b/.github/workflows/github-actions @@ -0,0 +1,32 @@ +name: Build and Test + +on: + pull_request: + branches: + - main + types: + - opened + - synchronize + - reopened + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup Java + uses: actions/setup-java@v1 + with: + java-version: 17 + + - name: Spotless Check + run: ./gradlew spotlessCheck + + - name: Detekt Check + run: ./gradlew detekt + + - name: Run Tests + run: ./gradlew test diff --git a/README.md b/README.md index 70d4d631..997c2f93 100644 --- a/README.md +++ b/README.md @@ -49,38 +49,28 @@ After installing, creating new features in the correct template structure should -## Project Structure -Android template project has three top-level packages: `core`, `designsystem` and `features`. Overall package structure looks like following -- `core` - - `extensions` - - `injection` - - `network` - - `persistence` - - `ui` -- `designsystem` - - `components` - - `theme` -- `features` - - `nstack` - - `feature1` - - `data` - - `domain` - - `injection` - - `ui` - -### `core` package -Core package is meant to be Domain-agnostic. It means that it should never reference anything project specific. Instead, it serves as a home for components that can be part of any project. This includes extensions on Kotlin Classes, Utility classes, Base classes, Compose layouts and Compose Effects and Modifiers that are behavioural rather then UI emitting - -### `designsystem` package -The design system package contains the building blocks for your application's UI. The main thing you will find here is `Theme`. This template is using custom `Theme` provider for Jetpack Compose while having `Material Theme` as its foundation. This allows to tweak `Colors` and `Typography` so it reflects actual Design System that is used on the project and supply custom properties like `Dimensions` - -Another part of the design system are components. Examples of `designsystem` components are Buttons, TopBars, TextFields and so on. The template provides `AppButton` `AppTextField` and `AppTopBar` that you can modify and tweak and use throughout the project. [Learn more about design system here](./docs/DESIGN_SYSTEM.md) - - -### `features` package -Features package contains the most important part of any project. A Feature typically contains all the necessary code(and resources + assets if migrated to multi module) required to implement a specific application functionality, such as a login screen, shopping cart, or authentication. It may also have its own sets of dependencies, like third-party libraries or other features. [Each feature is following Clean Architecture Principles and has a three-layer split](#architecture) +## Project Structure & Modules +Android template project has a modular structure and has following mopdules: `:core`, `:designsystem` and `:app`. The intention is to make this template as flexible as possible by introducing shared modules while having the all the features reside in `:app` module. In case project grows, this allows to easily decouple features from `:app` module and/or introduce new features as part of separate module. +![](./resources/moduels.svg) +### `core` module +Core module is meant to be Domain-agnostic. It means that it should never reference anything project specific. Instead, it serves as a home for components that can be part of any project. This includes extensions on Kotlin Classes, Utility classes, Base classes, Compose layouts and Compose Effects and Modifiers that are behavioural rather then UI emitting + + +### `designsystem` module +The design system module contains the building blocks for your application's UI. The main thing you will find here is `Theme`. This template is using custom `Theme` provider for Jetpack Compose while having `Material Theme` as its foundation. This allows to tweak `Colors` and `Typography` so it reflects actual Design System that is used on the project and supply custom properties like `Dimensions` + +Another part of the design system are components. Examples of `designsystem` components are Buttons, TopBars, TextFields and so on. The template provides `AppButton` `AppTextField` and `AppTopBar` that you can modify and tweak and use throughout the project. + + +### `app` module +This is a main modules that contains feature packages - the meat of any project. A Feature typically contains all the necessary code, resources and assets required to implement a specific application functionality, such as a login screen, shopping cart, or authentication. It may also have its own sets of dependencies, like third-party libraries or other features. + +#### Feature modules +While the template doesn't really have feature modules and every feature is part of the `:app` module, it is adviced to make use of feature modules in case the you see there is good candidate for it. It will especially benefit mid to large sized projects under active development + + Each feature (module or not) is following [Clean Architecture Principles and has a three-layer split](#architecture) ## Architecture Template implements [Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) and follows [best practices](https://developer.android.com/topic/architecture) provided by Google with some tweaks here and there @@ -95,7 +85,7 @@ The domain layer contains the application's business logic. This layer should on The data layer is where the actual interactions happen between different data sources. This layer “implements” parts of the Domain layer and communicates with the APIs, Databases, and other services and SDKs. -![](/docs/assets/arch.svg) +![](/resources/arch.svg) ## Flavors diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2b3b593e..1538822b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,4 +1,3 @@ - @file:Suppress("UnstableApiUsage") // TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed @Suppress("DSL_SCOPE_VIOLATION") @@ -9,6 +8,7 @@ plugins { alias(libs.plugins.ksp) alias(libs.plugins.hilt) id("dk.nstack.translation.plugin") + alias(libs.plugins.convention.android.application) } val nStackKey = "LqWLm621BwIxNRzdrei88pKhIIEI2EE8ni8r" @@ -21,14 +21,11 @@ translation { } android { - compileSdk = 34 namespace = "com.monstarlab" flavorDimensions += "default" defaultConfig { manifestPlaceholders += mapOf("appId" to nStackAppId, "apiKey" to nStackKey) applicationId = "com.monstarlab" - minSdk = 23 - targetSdk = 34 versionCode = 1 versionName = "1.0.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" @@ -63,28 +60,17 @@ android { buildConfigField("String", "API_URL", "\"https://reqres.in/api/\"") } } - buildFeatures { - viewBinding = true - compose = true - } - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get() - } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - kotlin { - jvmToolchain { - languageVersion.set(JavaLanguageVersion.of(JavaVersion.VERSION_17.toString())) - } - } + packaging { resources.excludes.add("META-INF/versions/9/previous-compilation-data.bin") } } +kotlin { + jvmToolchain(17) +} + configurations { create("devDebugImplementation") } @@ -109,6 +95,8 @@ dependencies { // Compose implementation(platform(libs.android.compose.bom)) implementation(libs.bundles.android.compose.core) + implementation(libs.android.compose.material) + implementation(libs.android.compose.material.windowsize) implementation(libs.android.activity.compose) implementation(libs.android.lifecycle.viewmodel.compose) implementation(libs.bundles.google.accompanist) @@ -132,4 +120,6 @@ dependencies { testImplementation(libs.bundles.test) androidTestImplementation(libs.bundles.android.test) + implementation(project(":core")) + implementation(project(":designsystem")) } diff --git a/app/src/main/java/com/monstarlab/features/buildconfig/AppBuildConfiguration.kt b/app/src/main/java/com/monstarlab/features/buildconfig/AppBuildConfiguration.kt new file mode 100644 index 00000000..98145be0 --- /dev/null +++ b/app/src/main/java/com/monstarlab/features/buildconfig/AppBuildConfiguration.kt @@ -0,0 +1,27 @@ +package com.monstarlab.features.buildconfig + +import com.monstarlab.BuildConfig +import com.monstarlab.core.config.AppFlavour +import com.monstarlab.core.config.AppVersion +import com.monstarlab.core.config.BuildConfiguration +import com.monstarlab.core.config.NetworkConfig +import javax.inject.Inject + +class AppBuildConfiguration @Inject constructor() : BuildConfiguration { + override val flavour: AppFlavour + get() { + return when (BuildConfig.FLAVOR) { + "development" -> AppFlavour.Development + "staging" -> AppFlavour.Staging + "production" -> AppFlavour.Production + else -> throw IllegalStateException( + "Flavour ${BuildConfig.FLAVOR} is not supported", + ) + } + } + override val version: AppVersion = AppVersion( + versionName = BuildConfig.VERSION_NAME, + buildNumber = BuildConfig.VERSION_CODE, + ) + override val networkConfig: NetworkConfig = NetworkConfig(BuildConfig.API_URL) +} diff --git a/app/src/main/java/com/monstarlab/features/buildconfig/BuildConfigurationModule.kt b/app/src/main/java/com/monstarlab/features/buildconfig/BuildConfigurationModule.kt new file mode 100644 index 00000000..01469d00 --- /dev/null +++ b/app/src/main/java/com/monstarlab/features/buildconfig/BuildConfigurationModule.kt @@ -0,0 +1,17 @@ +package com.monstarlab.features.buildconfig + +import com.monstarlab.core.config.BuildConfiguration +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +interface BuildConfigurationModule { + + @Binds + @Singleton + fun bindBuildConfiguration(appBuildConfiguration: AppBuildConfiguration): BuildConfiguration +} diff --git a/app/src/main/java/com/monstarlab/features/nstack/domain/usecase/SetupNstackUseCase.kt b/app/src/main/java/com/monstarlab/features/nstack/domain/usecase/SetupNstackUseCase.kt index 75e7874a..fcb4d31f 100644 --- a/app/src/main/java/com/monstarlab/features/nstack/domain/usecase/SetupNstackUseCase.kt +++ b/app/src/main/java/com/monstarlab/features/nstack/domain/usecase/SetupNstackUseCase.kt @@ -1,7 +1,7 @@ package com.monstarlab.features.nstack.domain.usecase +import com.monstarlab.core.coroutines.IoDispatcher import com.monstarlab.core.extensions.suspendRunCatching -import com.monstarlab.core.injection.IoDispatcher import dk.nodes.nstack.kotlin.NStack import dk.nodes.nstack.kotlin.models.AppOpenData import javax.inject.Inject diff --git a/build-logic/convention/.gitignore b/build-logic/convention/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/build-logic/convention/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts new file mode 100644 index 00000000..7de0e64f --- /dev/null +++ b/build-logic/convention/build.gradle.kts @@ -0,0 +1,28 @@ +plugins { + `kotlin-dsl` +} + +group = "com.monstarlab.buildlogic" + + +dependencies { + compileOnly(libs.android.gradle.plugin) + compileOnly(libs.kotlin.gradle.plugin) +} + +gradlePlugin { + /** + * Register convention plugins so they are available in the build scripts of the application + */ + plugins { + register("conventionAndroidLib") { + id = "convention.android.library" + implementationClass = "com.monstarlab.convention.AndroidLibConventionPlugin" + } + + register("conventionAndroidApp") { + id = "convention.android.application" + implementationClass = "com.monstarlab.convention.AndroidAppConventionPlugin" + } + } +} diff --git a/build-logic/convention/src/main/kotlin/com/monstarlab/convention/AndroidAppConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/monstarlab/convention/AndroidAppConventionPlugin.kt new file mode 100644 index 00000000..10869208 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/monstarlab/convention/AndroidAppConventionPlugin.kt @@ -0,0 +1,28 @@ +package com.monstarlab.convention + +import com.android.build.api.dsl.ApplicationExtension +import com.monstarlab.convention.extensions.libs +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure + +class AndroidAppConventionPlugin : Plugin { + override fun apply(target: Project) { + target.configure { + compileSdk = AndroidConfiguration.COMPILE_SDK + defaultConfig { + targetSdk = AndroidConfiguration.TARGET_SDK + minSdk = AndroidConfiguration.MIN_SDK + } + + buildFeatures { + compose = true + buildConfig = true + } + composeOptions { + kotlinCompilerExtensionVersion = target.rootProject.libs.findVersion("compose_compiler").get().toString() + } + } + + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/com/monstarlab/convention/AndroidConfig.kt b/build-logic/convention/src/main/kotlin/com/monstarlab/convention/AndroidConfig.kt new file mode 100644 index 00000000..4104cc5a --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/monstarlab/convention/AndroidConfig.kt @@ -0,0 +1,9 @@ +package com.monstarlab.convention + + +internal object AndroidConfiguration { + const val COMPILE_SDK = 34 + const val TARGET_SDK = 34 + const val MIN_SDK = 23 +} + diff --git a/build-logic/convention/src/main/kotlin/com/monstarlab/convention/AndroidLibConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/monstarlab/convention/AndroidLibConventionPlugin.kt new file mode 100644 index 00000000..646b3ad0 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/monstarlab/convention/AndroidLibConventionPlugin.kt @@ -0,0 +1,27 @@ +package com.monstarlab.convention + +import com.android.build.gradle.LibraryExtension +import com.monstarlab.convention.extensions.libs +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure + +class AndroidLibConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + extensions.configure { + compileSdk = AndroidConfiguration.COMPILE_SDK + defaultConfig { + minSdk = AndroidConfiguration.MIN_SDK + } + buildFeatures { + compose = true + buildConfig = true + } + composeOptions { + kotlinCompilerExtensionVersion = target.rootProject.libs.findVersion("compose_compiler").get().toString() + } + } + } + } +} diff --git a/build-logic/convention/src/main/kotlin/com/monstarlab/convention/extensions/Extensions.kt b/build-logic/convention/src/main/kotlin/com/monstarlab/convention/extensions/Extensions.kt new file mode 100644 index 00000000..52516c4c --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/monstarlab/convention/extensions/Extensions.kt @@ -0,0 +1,10 @@ +package com.monstarlab.convention.extensions + +import org.gradle.api.Project +import org.gradle.api.artifacts.VersionCatalog +import org.gradle.api.artifacts.VersionCatalogsExtension +import org.gradle.kotlin.dsl.getByType + + +internal val Project.libs: VersionCatalog get() = + extensions.getByType().named("libs") \ No newline at end of file diff --git a/build-logic/gradle.properties b/build-logic/gradle.properties new file mode 100644 index 00000000..1c9073eb --- /dev/null +++ b/build-logic/gradle.properties @@ -0,0 +1,4 @@ +# Gradle properties are not passed to included builds https://github.com/gradle/gradle/issues/2534 +org.gradle.parallel=true +org.gradle.caching=true +org.gradle.configureondemand=true diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts new file mode 100644 index 00000000..8d885091 --- /dev/null +++ b/build-logic/settings.gradle.kts @@ -0,0 +1,13 @@ +dependencyResolutionManagement { + repositories { + google() + mavenCentral() + } + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} + +include(":convention") diff --git a/build.gradle.kts b/build.gradle.kts index c2bd177c..7267c40e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,7 +11,10 @@ buildscript { @Suppress("DSL_SCOPE_VIOLATION") plugins { alias(libs.plugins.android.application) apply false + alias(libs.plugins.android.library) apply false alias(libs.plugins.kotlin.android) apply false + alias(libs.plugins.convention.android.library) apply false + alias(libs.plugins.convention.android.application) apply false alias(libs.plugins.detekt) apply false alias(libs.plugins.spotless) alias(libs.plugins.hilt) apply false diff --git a/core/.gitignore b/core/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/core/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/core/build.gradle.kts b/core/build.gradle.kts new file mode 100644 index 00000000..2c0a4c4f --- /dev/null +++ b/core/build.gradle.kts @@ -0,0 +1,46 @@ +@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.hilt) + alias(libs.plugins.ksp) + alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.convention.android.library) +} + +android { + namespace = "com.monstarlab.core" +} + +kotlin { + jvmToolchain(17) +} + +dependencies { + // Kotlin + implementation(libs.bundles.kotlin) + implementation(libs.kotlin.serialization.json) + + // Android + implementation(libs.android.datastore.preferences) + + // Compose + implementation(platform(libs.android.compose.bom)) + implementation(libs.bundles.android.compose.core) + implementation(libs.android.compose.material) + implementation(libs.bundles.google.accompanist) + + // Injection + implementation(libs.hilt.android) + ksp(libs.hilt.compiler) + + // Networking + implementation(libs.retrofit) + implementation(libs.retrofit.converter) + implementation(libs.okhttp.logger) + + // Other + implementation(libs.timber) + debugImplementation(libs.chucker.op) + releaseImplementation(libs.chucker.noop) +} \ No newline at end of file diff --git a/core/src/main/java/com/monstarlab/core/config/AppFlavour.kt b/core/src/main/java/com/monstarlab/core/config/AppFlavour.kt new file mode 100644 index 00000000..b5d12e4c --- /dev/null +++ b/core/src/main/java/com/monstarlab/core/config/AppFlavour.kt @@ -0,0 +1,7 @@ +package com.monstarlab.core.config + +enum class AppFlavour { + Development, + Staging, + Production, +} diff --git a/core/src/main/java/com/monstarlab/core/config/AppVersion.kt b/core/src/main/java/com/monstarlab/core/config/AppVersion.kt new file mode 100644 index 00000000..1be80e8a --- /dev/null +++ b/core/src/main/java/com/monstarlab/core/config/AppVersion.kt @@ -0,0 +1,10 @@ +package com.monstarlab.core.config + +data class AppVersion( + val versionName: String, + val buildNumber: Int, +) { + override fun toString(): String { + return "$versionName ($buildNumber)" + } +} diff --git a/core/src/main/java/com/monstarlab/core/config/BuildConfiguration.kt b/core/src/main/java/com/monstarlab/core/config/BuildConfiguration.kt new file mode 100644 index 00000000..2c6d8d1f --- /dev/null +++ b/core/src/main/java/com/monstarlab/core/config/BuildConfiguration.kt @@ -0,0 +1,7 @@ +package com.monstarlab.core.config + +interface BuildConfiguration { + val flavour: AppFlavour + val version: AppVersion + val networkConfig: NetworkConfig +} diff --git a/core/src/main/java/com/monstarlab/core/config/NetworkConfig.kt b/core/src/main/java/com/monstarlab/core/config/NetworkConfig.kt new file mode 100644 index 00000000..20ab62ae --- /dev/null +++ b/core/src/main/java/com/monstarlab/core/config/NetworkConfig.kt @@ -0,0 +1,5 @@ +package com.monstarlab.core.config + +data class NetworkConfig( + val baseUrl: String, +) diff --git a/app/src/main/java/com/monstarlab/core/injection/CoroutineQualifiers.kt b/core/src/main/java/com/monstarlab/core/coroutines/CoroutineQualifiers.kt similarity index 90% rename from app/src/main/java/com/monstarlab/core/injection/CoroutineQualifiers.kt rename to core/src/main/java/com/monstarlab/core/coroutines/CoroutineQualifiers.kt index 1663a36a..4e9fa079 100644 --- a/app/src/main/java/com/monstarlab/core/injection/CoroutineQualifiers.kt +++ b/core/src/main/java/com/monstarlab/core/coroutines/CoroutineQualifiers.kt @@ -1,4 +1,4 @@ -package com.monstarlab.core.injection +package com.monstarlab.core.coroutines import javax.inject.Qualifier diff --git a/app/src/main/java/com/monstarlab/core/injection/CoroutinesModule.kt b/core/src/main/java/com/monstarlab/core/coroutines/CoroutinesModule.kt similarity index 95% rename from app/src/main/java/com/monstarlab/core/injection/CoroutinesModule.kt rename to core/src/main/java/com/monstarlab/core/coroutines/CoroutinesModule.kt index 76fb89d6..a1fb8701 100644 --- a/app/src/main/java/com/monstarlab/core/injection/CoroutinesModule.kt +++ b/core/src/main/java/com/monstarlab/core/coroutines/CoroutinesModule.kt @@ -1,4 +1,4 @@ -package com.monstarlab.core.injection +package com.monstarlab.core.coroutines import dagger.Module import dagger.Provides diff --git a/app/src/main/java/com/monstarlab/core/error/ErrorModel.kt b/core/src/main/java/com/monstarlab/core/error/ErrorModel.kt similarity index 99% rename from app/src/main/java/com/monstarlab/core/error/ErrorModel.kt rename to core/src/main/java/com/monstarlab/core/error/ErrorModel.kt index dd2482e4..6ddef76b 100644 --- a/app/src/main/java/com/monstarlab/core/error/ErrorModel.kt +++ b/core/src/main/java/com/monstarlab/core/error/ErrorModel.kt @@ -14,6 +14,7 @@ sealed interface ErrorModel { object IOError : Connection() object UnknownHost : Connection() } + data class Unknown(val throwable: Throwable) : ErrorModel } diff --git a/app/src/main/java/com/monstarlab/core/error/ErrorModelWithDisplayableMessage.kt b/core/src/main/java/com/monstarlab/core/error/ErrorModelWithDisplayableMessage.kt similarity index 100% rename from app/src/main/java/com/monstarlab/core/error/ErrorModelWithDisplayableMessage.kt rename to core/src/main/java/com/monstarlab/core/error/ErrorModelWithDisplayableMessage.kt diff --git a/app/src/main/java/com/monstarlab/core/extensions/Extensions.kt b/core/src/main/java/com/monstarlab/core/extensions/Extensions.kt similarity index 100% rename from app/src/main/java/com/monstarlab/core/extensions/Extensions.kt rename to core/src/main/java/com/monstarlab/core/extensions/Extensions.kt diff --git a/app/src/main/java/com/monstarlab/core/extensions/FlowExtensions.kt b/core/src/main/java/com/monstarlab/core/extensions/FlowExtensions.kt similarity index 100% rename from app/src/main/java/com/monstarlab/core/extensions/FlowExtensions.kt rename to core/src/main/java/com/monstarlab/core/extensions/FlowExtensions.kt diff --git a/app/src/main/java/com/monstarlab/core/extensions/StringExtensions.kt b/core/src/main/java/com/monstarlab/core/extensions/StringExtensions.kt similarity index 100% rename from app/src/main/java/com/monstarlab/core/extensions/StringExtensions.kt rename to core/src/main/java/com/monstarlab/core/extensions/StringExtensions.kt diff --git a/app/src/main/java/com/monstarlab/core/network/OkHttpModule.kt b/core/src/main/java/com/monstarlab/core/network/OkHttpModule.kt similarity index 88% rename from app/src/main/java/com/monstarlab/core/network/OkHttpModule.kt rename to core/src/main/java/com/monstarlab/core/network/OkHttpModule.kt index e36825a6..bd918bcb 100644 --- a/app/src/main/java/com/monstarlab/core/network/OkHttpModule.kt +++ b/core/src/main/java/com/monstarlab/core/network/OkHttpModule.kt @@ -3,7 +3,8 @@ package com.monstarlab.core.network import android.content.Context import com.chuckerteam.chucker.api.ChuckerInterceptor import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory -import com.monstarlab.BuildConfig +import com.monstarlab.core.BuildConfig +import com.monstarlab.core.config.BuildConfiguration import com.monstarlab.core.network.errorhandling.ApiErrorInterceptor import dagger.Module import dagger.Provides @@ -47,10 +48,10 @@ class OkHttpModule { @ExperimentalSerializationApi @Provides @Singleton - fun provideRetrofit(client: OkHttpClient): Retrofit { + fun provideRetrofit(client: OkHttpClient, buildConfiguration: BuildConfiguration): Retrofit { return Retrofit.Builder() .client(client) - .baseUrl(BuildConfig.API_URL) + .baseUrl(buildConfiguration.networkConfig.baseUrl) .addConverterFactory( json.asConverterFactory("application/json".toMediaType()), ) diff --git a/app/src/main/java/com/monstarlab/core/network/errorhandling/ApiErrorDTO.kt b/core/src/main/java/com/monstarlab/core/network/errorhandling/ApiErrorDTO.kt similarity index 100% rename from app/src/main/java/com/monstarlab/core/network/errorhandling/ApiErrorDTO.kt rename to core/src/main/java/com/monstarlab/core/network/errorhandling/ApiErrorDTO.kt diff --git a/app/src/main/java/com/monstarlab/core/network/errorhandling/ApiErrorInterceptor.kt b/core/src/main/java/com/monstarlab/core/network/errorhandling/ApiErrorInterceptor.kt similarity index 82% rename from app/src/main/java/com/monstarlab/core/network/errorhandling/ApiErrorInterceptor.kt rename to core/src/main/java/com/monstarlab/core/network/errorhandling/ApiErrorInterceptor.kt index 53a99ed8..b921caee 100644 --- a/app/src/main/java/com/monstarlab/core/network/errorhandling/ApiErrorInterceptor.kt +++ b/core/src/main/java/com/monstarlab/core/network/errorhandling/ApiErrorInterceptor.kt @@ -6,7 +6,6 @@ import okhttp3.Response import okhttp3.ResponseBody.Companion.toResponseBody import timber.log.Timber import javax.inject.Inject -import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json /** @@ -25,15 +24,15 @@ class ApiErrorInterceptor @Inject constructor( if (response.isSuccessful) { return response } - val errorBody = response.body.string() + val errorBody = response.body?.string() val errorDtoResult = runCatching { - json.decodeFromString(errorBody) + json.decodeFromString(checkNotNull(errorBody)) } if (errorDtoResult.isSuccess) { throw errorDtoResult.getOrThrow().toApiError(response.code) } else { - val newErrorBody = errorBody.toResponseBody("application/json".toMediaType()) + val newErrorBody = errorBody?.toResponseBody("application/json".toMediaType()) Timber.e("Failed to deserialize error body: ${errorDtoResult.exceptionOrNull()}") return response.newBuilder().body(newErrorBody).build() } diff --git a/app/src/main/java/com/monstarlab/core/network/errorhandling/ApiException.kt b/core/src/main/java/com/monstarlab/core/network/errorhandling/ApiException.kt similarity index 100% rename from app/src/main/java/com/monstarlab/core/network/errorhandling/ApiException.kt rename to core/src/main/java/com/monstarlab/core/network/errorhandling/ApiException.kt diff --git a/app/src/main/java/com/monstarlab/core/persistence/Data.md b/core/src/main/java/com/monstarlab/core/persistence/Data.md similarity index 100% rename from app/src/main/java/com/monstarlab/core/persistence/Data.md rename to core/src/main/java/com/monstarlab/core/persistence/Data.md diff --git a/app/src/main/java/com/monstarlab/core/persistence/DataSource.kt b/core/src/main/java/com/monstarlab/core/persistence/DataSource.kt similarity index 100% rename from app/src/main/java/com/monstarlab/core/persistence/DataSource.kt rename to core/src/main/java/com/monstarlab/core/persistence/DataSource.kt diff --git a/app/src/main/java/com/monstarlab/core/persistence/SharedPreferenceDataStore.kt b/core/src/main/java/com/monstarlab/core/persistence/SharedPreferenceDataStore.kt similarity index 96% rename from app/src/main/java/com/monstarlab/core/persistence/SharedPreferenceDataStore.kt rename to core/src/main/java/com/monstarlab/core/persistence/SharedPreferenceDataStore.kt index 338fa351..22834d64 100644 --- a/app/src/main/java/com/monstarlab/core/persistence/SharedPreferenceDataStore.kt +++ b/core/src/main/java/com/monstarlab/core/persistence/SharedPreferenceDataStore.kt @@ -11,7 +11,7 @@ import kotlinx.serialization.SerializationException import kotlinx.serialization.builtins.ListSerializer import kotlinx.serialization.json.Json -abstract class SharedPreferenceDataStore constructor( +abstract class SharedPreferenceDataStore( private val dataStore: DataStore, private val serializer: KSerializer, ) : DataSource { diff --git a/app/src/main/java/com/monstarlab/core/persistence/SingleDataSource.kt b/core/src/main/java/com/monstarlab/core/persistence/SingleDataSource.kt similarity index 100% rename from app/src/main/java/com/monstarlab/core/persistence/SingleDataSource.kt rename to core/src/main/java/com/monstarlab/core/persistence/SingleDataSource.kt diff --git a/app/src/main/java/com/monstarlab/core/persistence/SingleSharedPreferenceDataStore.kt b/core/src/main/java/com/monstarlab/core/persistence/SingleSharedPreferenceDataStore.kt similarity index 95% rename from app/src/main/java/com/monstarlab/core/persistence/SingleSharedPreferenceDataStore.kt rename to core/src/main/java/com/monstarlab/core/persistence/SingleSharedPreferenceDataStore.kt index 1259a801..fe4780ce 100644 --- a/app/src/main/java/com/monstarlab/core/persistence/SingleSharedPreferenceDataStore.kt +++ b/core/src/main/java/com/monstarlab/core/persistence/SingleSharedPreferenceDataStore.kt @@ -11,7 +11,7 @@ import kotlinx.serialization.KSerializer import kotlinx.serialization.SerializationException import kotlinx.serialization.json.Json -abstract class SingleSharedPreferenceDataStore constructor( +abstract class SingleSharedPreferenceDataStore( private val dataStore: DataStore, private val serializer: KSerializer, ) : SingleDataSource { diff --git a/app/src/main/java/com/monstarlab/core/persistence/injection/DataStoreModule.kt b/core/src/main/java/com/monstarlab/core/persistence/injection/DataStoreModule.kt similarity index 100% rename from app/src/main/java/com/monstarlab/core/persistence/injection/DataStoreModule.kt rename to core/src/main/java/com/monstarlab/core/persistence/injection/DataStoreModule.kt diff --git a/app/src/main/java/com/monstarlab/core/ui/ComposeFragment.kt b/core/src/main/java/com/monstarlab/core/ui/ComposeFragment.kt similarity index 100% rename from app/src/main/java/com/monstarlab/core/ui/ComposeFragment.kt rename to core/src/main/java/com/monstarlab/core/ui/ComposeFragment.kt diff --git a/app/src/main/java/com/monstarlab/core/ui/effects/SystemUISideEffect.kt b/core/src/main/java/com/monstarlab/core/ui/effects/SystemUISideEffect.kt similarity index 100% rename from app/src/main/java/com/monstarlab/core/ui/effects/SystemUISideEffect.kt rename to core/src/main/java/com/monstarlab/core/ui/effects/SystemUISideEffect.kt diff --git a/app/src/main/java/com/monstarlab/core/ui/extensions/ColorExtensions.kt b/core/src/main/java/com/monstarlab/core/ui/extensions/ColorExtensions.kt similarity index 100% rename from app/src/main/java/com/monstarlab/core/ui/extensions/ColorExtensions.kt rename to core/src/main/java/com/monstarlab/core/ui/extensions/ColorExtensions.kt diff --git a/app/src/main/java/com/monstarlab/core/ui/extensions/ContextExtensions.kt b/core/src/main/java/com/monstarlab/core/ui/extensions/ContextExtensions.kt similarity index 100% rename from app/src/main/java/com/monstarlab/core/ui/extensions/ContextExtensions.kt rename to core/src/main/java/com/monstarlab/core/ui/extensions/ContextExtensions.kt diff --git a/app/src/main/java/com/monstarlab/core/ui/extensions/LazyLayoutExtensions.kt b/core/src/main/java/com/monstarlab/core/ui/extensions/LazyLayoutExtensions.kt similarity index 100% rename from app/src/main/java/com/monstarlab/core/ui/extensions/LazyLayoutExtensions.kt rename to core/src/main/java/com/monstarlab/core/ui/extensions/LazyLayoutExtensions.kt diff --git a/app/src/main/java/com/monstarlab/core/ui/extensions/TextStyleExtensions.kt b/core/src/main/java/com/monstarlab/core/ui/extensions/TextStyleExtensions.kt similarity index 100% rename from app/src/main/java/com/monstarlab/core/ui/extensions/TextStyleExtensions.kt rename to core/src/main/java/com/monstarlab/core/ui/extensions/TextStyleExtensions.kt diff --git a/app/src/main/java/com/monstarlab/core/ui/layout/ColumnWithSeparators.kt b/core/src/main/java/com/monstarlab/core/ui/layout/ColumnWithSeparators.kt similarity index 94% rename from app/src/main/java/com/monstarlab/core/ui/layout/ColumnWithSeparators.kt rename to core/src/main/java/com/monstarlab/core/ui/layout/ColumnWithSeparators.kt index 74a0f928..ca08b191 100644 --- a/app/src/main/java/com/monstarlab/core/ui/layout/ColumnWithSeparators.kt +++ b/core/src/main/java/com/monstarlab/core/ui/layout/ColumnWithSeparators.kt @@ -1,6 +1,5 @@ package com.monstarlab.core.ui.layout -import androidx.compose.material.Divider import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -10,7 +9,7 @@ import androidx.compose.ui.tooling.preview.Preview @Composable fun ColumnWithSeparators( modifier: Modifier = Modifier, - separator: @Composable () -> Unit = { Divider() }, + separator: @Composable () -> Unit = {}, content: @Composable () -> Unit, ) { SubcomposeLayout(modifier) { constraints -> diff --git a/app/src/main/java/com/monstarlab/core/ui/previews/LightDarkPreview.kt b/core/src/main/java/com/monstarlab/core/ui/previews/LightDarkPreview.kt similarity index 100% rename from app/src/main/java/com/monstarlab/core/ui/previews/LightDarkPreview.kt rename to core/src/main/java/com/monstarlab/core/ui/previews/LightDarkPreview.kt diff --git a/designsystem/.gitignore b/designsystem/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/designsystem/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/designsystem/build.gradle.kts b/designsystem/build.gradle.kts new file mode 100644 index 00000000..d2f463e1 --- /dev/null +++ b/designsystem/build.gradle.kts @@ -0,0 +1,25 @@ +@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.convention.android.library) +} + +android { + namespace = "com.monstarlab.designsystem" +} + +kotlin { + jvmToolchain(17) +} + +dependencies { + // Compose + implementation(platform(libs.android.compose.bom)) + implementation(libs.bundles.android.compose.core) + implementation(libs.android.compose.material) + implementation(libs.android.compose.material.windowsize) + debugImplementation(libs.android.compose.ui.tooling) + + implementation(project(":core")) +} \ No newline at end of file diff --git a/app/src/main/java/com/monstarlab/designsystem/components/AppTopBar.kt b/designsystem/src/main/java/com/monstarlab/designsystem/components/AppTopBar.kt similarity index 100% rename from app/src/main/java/com/monstarlab/designsystem/components/AppTopBar.kt rename to designsystem/src/main/java/com/monstarlab/designsystem/components/AppTopBar.kt diff --git a/app/src/main/java/com/monstarlab/designsystem/components/appbutton/AppButton.kt b/designsystem/src/main/java/com/monstarlab/designsystem/components/appbutton/AppButton.kt similarity index 100% rename from app/src/main/java/com/monstarlab/designsystem/components/appbutton/AppButton.kt rename to designsystem/src/main/java/com/monstarlab/designsystem/components/appbutton/AppButton.kt diff --git a/app/src/main/java/com/monstarlab/designsystem/components/appbutton/AppButtonType.kt b/designsystem/src/main/java/com/monstarlab/designsystem/components/appbutton/AppButtonType.kt similarity index 100% rename from app/src/main/java/com/monstarlab/designsystem/components/appbutton/AppButtonType.kt rename to designsystem/src/main/java/com/monstarlab/designsystem/components/appbutton/AppButtonType.kt diff --git a/app/src/main/java/com/monstarlab/designsystem/components/apptextfield/AppTextField.kt b/designsystem/src/main/java/com/monstarlab/designsystem/components/apptextfield/AppTextField.kt similarity index 100% rename from app/src/main/java/com/monstarlab/designsystem/components/apptextfield/AppTextField.kt rename to designsystem/src/main/java/com/monstarlab/designsystem/components/apptextfield/AppTextField.kt diff --git a/app/src/main/java/com/monstarlab/designsystem/theme/AppTheme.kt b/designsystem/src/main/java/com/monstarlab/designsystem/theme/AppTheme.kt similarity index 100% rename from app/src/main/java/com/monstarlab/designsystem/theme/AppTheme.kt rename to designsystem/src/main/java/com/monstarlab/designsystem/theme/AppTheme.kt diff --git a/app/src/main/java/com/monstarlab/designsystem/theme/Colors.kt b/designsystem/src/main/java/com/monstarlab/designsystem/theme/Colors.kt similarity index 100% rename from app/src/main/java/com/monstarlab/designsystem/theme/Colors.kt rename to designsystem/src/main/java/com/monstarlab/designsystem/theme/Colors.kt diff --git a/app/src/main/java/com/monstarlab/designsystem/theme/Shapes.kt b/designsystem/src/main/java/com/monstarlab/designsystem/theme/Shapes.kt similarity index 100% rename from app/src/main/java/com/monstarlab/designsystem/theme/Shapes.kt rename to designsystem/src/main/java/com/monstarlab/designsystem/theme/Shapes.kt diff --git a/app/src/main/java/com/monstarlab/designsystem/theme/dimensions/Dimensions.kt b/designsystem/src/main/java/com/monstarlab/designsystem/theme/dimensions/Dimensions.kt similarity index 100% rename from app/src/main/java/com/monstarlab/designsystem/theme/dimensions/Dimensions.kt rename to designsystem/src/main/java/com/monstarlab/designsystem/theme/dimensions/Dimensions.kt diff --git a/app/src/main/java/com/monstarlab/designsystem/theme/dimensions/DimensionsProvider.kt b/designsystem/src/main/java/com/monstarlab/designsystem/theme/dimensions/DimensionsProvider.kt similarity index 100% rename from app/src/main/java/com/monstarlab/designsystem/theme/dimensions/DimensionsProvider.kt rename to designsystem/src/main/java/com/monstarlab/designsystem/theme/dimensions/DimensionsProvider.kt diff --git a/app/src/main/java/com/monstarlab/designsystem/theme/typography/AppTypography.kt b/designsystem/src/main/java/com/monstarlab/designsystem/theme/typography/AppTypography.kt similarity index 100% rename from app/src/main/java/com/monstarlab/designsystem/theme/typography/AppTypography.kt rename to designsystem/src/main/java/com/monstarlab/designsystem/theme/typography/AppTypography.kt diff --git a/app/src/main/java/com/monstarlab/designsystem/theme/typography/AppTypographyProvider.kt b/designsystem/src/main/java/com/monstarlab/designsystem/theme/typography/AppTypographyProvider.kt similarity index 100% rename from app/src/main/java/com/monstarlab/designsystem/theme/typography/AppTypographyProvider.kt rename to designsystem/src/main/java/com/monstarlab/designsystem/theme/typography/AppTypographyProvider.kt diff --git a/app/src/main/java/com/monstarlab/designsystem/theme/typography/FontFamily.kt b/designsystem/src/main/java/com/monstarlab/designsystem/theme/typography/FontFamily.kt similarity index 100% rename from app/src/main/java/com/monstarlab/designsystem/theme/typography/FontFamily.kt rename to designsystem/src/main/java/com/monstarlab/designsystem/theme/typography/FontFamily.kt diff --git a/app/src/main/java/com/monstarlab/designsystem/theme/typography/Typography.kt b/designsystem/src/main/java/com/monstarlab/designsystem/theme/typography/Typography.kt similarity index 100% rename from app/src/main/java/com/monstarlab/designsystem/theme/typography/Typography.kt rename to designsystem/src/main/java/com/monstarlab/designsystem/theme/typography/Typography.kt diff --git a/docs/DESIGN_SYSTEM.md b/docs/DESIGN_SYSTEM.md deleted file mode 100644 index 3e7de7a4..00000000 --- a/docs/DESIGN_SYSTEM.md +++ /dev/null @@ -1,84 +0,0 @@ -# Design System - -A design system is a comprehensive set of design elements, principles, and guidelines that provide a framework for defining and governing the overall visual and user interface (UI) design of a product or service. In software development, particularly in mobile app development, a design system typically includes a library of standardized UI components, themes, and styles that serve as the building blocks for creating consistent and cohesive UI screens. - - Essentially, a design system represents the implementation of the design decisions made by designers, translated into code, and applied throughout the entire product or service. - - - - - -## Approach - -In most cases, the very default design system on Android implements Material Design. That's how get our basic look for the Buttons, Top Bars, and behavior components like Bottom Sheets. While it is easy to use and modify, in most scenarios the Design System we, as developers, have to implement will be very different. It can have more colors, more text styles, and overall be very far from the Material Design APIs. - -As it doesn’t make much sense to implement a completely custom design system, the designsystem in the template serves as a bridge between Material Design and the specific Design System we have to implement. This is done by having custom Typography, Colors, and Dimensions classes that ultimately get translated into Material Design. This provides the following benefits: - -- Our colors and typography don't need to follow Material Guidelines. We can more or fewer colors depending on the actual design, and different typography - -- We can have custom properties hooked up with the Theme, which the normal Material Design System doesn’t provide, for example, Dimensions - -- We can still use components from the Material Theme, like Buttons, top bars, Cards, and Surfaces. And, given the custom colors, fonts were translated properly (for example custom cardBackgroundColor will be translated into surface color in material) they will work out of the box - - - -## Structure - -Currently, the structure of the design system is following - -- `designsystem` - - `components` - ui components, some may have separate packages - - `theme` - contains theme-related information - - `colors` - Colors that define design-system - - `typograpy` - Text styles that define design-system - - `AppTheme.kt ` - -Develops are free to add additional packages if they want to - -## Best practices - -### Components - -- **Generic and Distinct Naming**. Implement re-usable design system components in the Design system and make the name of these components. Since Material has its own Buttons and TopBars, the name of your components should be unique enough so you don't confuse the imports. For example AppButton , AppTopBar - -- **Make the API of your components as small and concise as possible.** Material components are very flexible and they all support Slot APIs, for example, you can put any @Composable into `material.Button` content property. This is great, but in most cases, all you need for such a button is a simple text as String. - -```kotlin -// GOOD -@Composable -fun AppButton( - text: String, - onClick: () -> Unit, - modifier: Modifier = Modifier, - enabled: Boolean = true, - isLoading: Boolean = false, - type: AppButtonType = AppButtonType.Filled, - -) -``` - - -- **Don’t reference your Domain.** The design system should not know about your domain models or render something specific to the features. They should stay as generic and reusable as possible. That goes both for the Component name and its implementation - -- **Extract complex components away from the features.** In case you have a custom component for some feature (fx some fancy-looking Slider), move all its complexity to one of the shared modules/packages (design system or core.ui) and make it generic. - - - -### Colors and Typography - -- **Expand and/or Shrink the AppTypography and AppColors to suit your needs.** Make it mirror the actual design system you are working with and then convert it to Material where it's possible. - -- **Don't hardcode colors.** While colors can be very tempting to hardcode always try to see if this color can fit into your design system somehow. Maybe its the same background color but with different alpha? - -- **Use generic color names, not actual colors.** Use names like background primary and error instead of actual colors like White Blue and Red. This will make it easy to adapt your design system and use different Theme types, like Dark Mode, or in case the app will go through White-labeling - -- **Don’t hardcode text styles.** This is mainly a concern for the properties that involve numbers: letterSpacing , fontSize lineHeight and etc. Always use your design system typography to reference that. On the other hand, making text bold is Ok . - -```kotlin -// OK -val headline3 = Theme.typography.headline3 -val headline3Bold = Theme.typography.headline3.copy(fontWeight = FontWeight.Bold) - -// Not ok -val body2 = Theme.typography.body1.copy(fontSize = 12.sp) -``` \ No newline at end of file diff --git a/docs/assets/arch.svg b/docs/assets/arch.svg deleted file mode 100644 index 52ac5766..00000000 --- a/docs/assets/arch.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 8145fa7b..80f9b0b6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,4 +21,12 @@ android.enableJetifier=true kotlin.code.style=official android.defaults.buildfeatures.buildconfig=true android.nonTransitiveRClass=false -android.nonFinalResIds=false \ No newline at end of file +android.nonFinalResIds=false +# +## Reduce size of R class +#android.nonTransitiveRClass=true +# +# Speed up the build +#org.gradle.caching=true +#org.gradle.parallel=true +##org.gradle.unsafe.configuration-cache=true \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9caeeaab..a1f7e9f7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,31 +1,34 @@ [versions] nstack = "3.2.9" -kotlin = "1.9.10" +kotlin = "1.9.20" ksp = "1.9.10-1.0.13" kotlin_coroutines = "1.7.3" retrofit = "2.9.0" -okhttp = "5.0.0-alpha.10" -compose_bom = "2023.09.00" -compose_compiler = "1.5.3" +okhttp = "4.12.0" +compose_bom = "2023.10.01" +compose_compiler = "1.5.4" hilt = "2.48" lifecycle = "2.6.2" -navigation = "2.7.2" +navigation = "2.7.5" datastore = "1.0.0" google_accompanist = "0.32.0" androidx_appcompat = "1.6.1" androidx_core = "1.9.0" -android_gradle = "8.1.1" +android_gradle = "8.1.4" chucker = "4.0.0" -mockk = "1.13.7" +mockk = "1.13.8" [plugins] spotless = { id = "com.diffplug.spotless", version = "6.22.0" } detekt = { id = "io.gitlab.arturbosch.detekt", version = "1.23.1" } kotlin_serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } android-application = { id = "com.android.application", version.ref = "android_gradle" } +android_library = { id = "com.android.library", version.ref = "android_gradle" } kotlin_android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } +convention-android-library = { id = "convention.android.library", version = "unspecified" } +convention-android-application = { id = "convention.android.application", version = "unspecified" } [libraries] #------------------------- @@ -41,12 +44,12 @@ kotlin_serialization_json = "org.jetbrains.kotlinx:kotlinx-serialization-json:1. # Android #------------------------- android_gradle_plugin = { module = "com.android.tools.build:gradle", version.ref = "android_gradle" } -android_fragment = { module = "androidx.fragment:fragment-ktx", version = "1.6.1" } -android_material = { group = "com.google.android.material", name = "material", version = "1.9.0" } +android_fragment = { module = "androidx.fragment:fragment-ktx", version = "1.6.2" } +android_material = { group = "com.google.android.material", name = "material", version = "1.10.0" } android_contraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version = "2.1.4" } android_appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidx-appcompat" } android_core = { group = "androidx.core", name = "core-ktx", version.ref = "androidx-core" } -android_activity_compose = { module = "androidx.activity:activity-compose", version = "1.7.2" } +android_activity_compose = { module = "androidx.activity:activity-compose", version = "1.8.1" } android_splash = { module = "androidx.core:core-splashscreen", version = "1.0.1"} #------------------------- # Android - Lifecycle @@ -57,7 +60,7 @@ android_lifecycle_common = { module = "androidx.lifecycle:lifecycle-common-java8 android_lifecycle_viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycle" } android_lifecycle_livedata = { module = "androidx.lifecycle:lifecycle-livedata-ktx", version.ref = "lifecycle" } android_lifecycle_viewmodel_compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycle" } -android_lifecycle_runtime_compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version = "2.7.0-alpha01" } +android_lifecycle_runtime_compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version = "2.7.0-rc01" } #------------------------- # Android - Hilt #------------------------- @@ -73,10 +76,12 @@ android_compose_material = { module = "androidx.compose.material:material" } android_compose_ui_util = { module = "androidx.compose.ui:ui-util" } android_compose_ui_tooling = { module = "androidx.compose.ui:ui-tooling" } android_compose_ui_tooling_preview = { module = "androidx.compose.ui:ui-tooling-preview" } +android_compose_foundation = { module = "androidx.compose.animation:animation" } +android_compose_animation = { module = "androidx.compose.foundation:foundation" } android_compose_runtime = { module = "androidx.compose.runtime:runtime-livedata" } android_compose_ui_test = { module = "androidx.compose.ui:ui-test-junit4" } android_compose_ui_test_manifest = { module = "androidx.compose.ui:ui-test-manifest" } -android_compose_material_windowsize = "androidx.compose.material3:material3-window-size-class:1.1.1" +android_compose_material_windowsize = "androidx.compose.material3:material3-window-size-class:1.1.2" #------------------------- # Android - Navigation #------------------------- @@ -139,10 +144,11 @@ android_core = [ android_compose_core = [ "android_compose_ui", - "android_compose_material", + "android_compose_foundation", + "android_compose_animation", "android_compose_ui_util", "android_compose_runtime", - "android_compose_material_windowsize" + "android_compose_ui_tooling_preview" ] android_lifecycle = [ diff --git a/resources/arch.svg b/resources/arch.svg new file mode 100644 index 00000000..a66ab16d --- /dev/null +++ b/resources/arch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/moduels.svg b/resources/moduels.svg new file mode 100644 index 00000000..75391e5b --- /dev/null +++ b/resources/moduels.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index ff6d6c5d..b2242344 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,4 +1,5 @@ pluginManagement { + includeBuild("build-logic") repositories { gradlePluginPortal() google() @@ -12,5 +13,8 @@ dependencyResolutionManagement { mavenCentral() } } +rootProject.name = "android-template" + include(":app") -rootProject.name = "android-template" \ No newline at end of file +include(":core") +include(":designsystem") \ No newline at end of file