Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/modules core designsystem #82

Merged
merged 53 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
af653d9
Create github-actions
Halulkin Sep 8, 2023
5324244
Create github-actions
Halulkin Sep 8, 2023
87e3c13
ci: replaced github-actions
Halulkin Sep 8, 2023
269a08a
Update github-actions
Halulkin Sep 8, 2023
c2befc9
Update github-actions
Halulkin Sep 8, 2023
7060931
feat: created a core module
Halulkin Sep 11, 2023
7f38bb4
feat: added core module to the app
Halulkin Sep 11, 2023
88c9086
refactor: moved error package to the core module
Halulkin Sep 11, 2023
7af479a
refactor: moved extensions package to the core module
Halulkin Sep 11, 2023
13863da
refactor: moved injection package to the core module
Halulkin Sep 11, 2023
e3bc4d8
feat: implemented AppModule di class to provide baseUrl from the app …
Halulkin Sep 12, 2023
0fbe680
refactor: moved network package to the core module
Halulkin Sep 12, 2023
ad2a43e
feat: updated provideRetrofit fun to receive baseUrl as param instead…
Halulkin Sep 12, 2023
7c54696
refactor: moved persistence package to the core module
Halulkin Sep 12, 2023
0f09889
refactor: moved ui package to the core module
Halulkin Sep 12, 2023
4e672b2
feat: added gitignore to the core module
Halulkin Sep 12, 2023
c85a9f3
feat: implemented designsystem module
Halulkin Sep 12, 2023
b58e89d
refactor: moved all designsystem packages from app module to the des…
Halulkin Sep 12, 2023
aea60f4
feat: implemented build-logic module
Halulkin Sep 12, 2023
846120f
feat: added gitignore to build-logic module
Halulkin Sep 12, 2023
d5c0fc7
feat: implemented AndroidLibraryConventionPlugin
Halulkin Sep 12, 2023
6eba099
feat: implemented Android configuration for the AndroidLibraryConvent…
Halulkin Sep 12, 2023
7dcf63d
feat: added convention.android.library plugin to the project
Halulkin Sep 12, 2023
6c7d83b
feat: updated core module with convention android library plugin
Halulkin Sep 12, 2023
21173aa
feat: updated designsystem module with convention android library plugin
Halulkin Sep 12, 2023
0d233ce
Merge branch 'monstar-lab-oss:main' into main
Halulkin Sep 18, 2023
09c785a
Merge branch 'main' into refator/modularisation
Halulkin Sep 18, 2023
449b249
chore: removed empty line form the gradle
Halulkin Sep 18, 2023
24645e2
build: migrated core gradle to the ksp and versions catalogue
Halulkin Sep 18, 2023
1532ecd
build: migrated designsystem to the versions catalogue
Halulkin Sep 18, 2023
2fe8e86
build: added android library plugin to the project gradle
Halulkin Sep 18, 2023
bd4c001
build: added android library plugin to the versions catalogue
Halulkin Sep 18, 2023
0d54f26
build: added android compose foundation and animation
Halulkin Sep 18, 2023
585e97b
build: added commented gradle properties to speedup the build
Halulkin Sep 18, 2023
1a149d2
refactor: removed material from core module
Halulkin Sep 18, 2023
79fd442
build: added material to the designsystem module
Halulkin Sep 18, 2023
6a72332
build: added material to the app module
Halulkin Sep 18, 2023
89a0ffa
refactor: implemented NetworkConfig to be provided to the OkHttpModul…
Halulkin Sep 18, 2023
efca725
build: upgraded ktlint to the version 0.48.1
Halulkin Sep 18, 2023
4f6f881
chore: spotless applied
Halulkin Sep 18, 2023
2259f34
build: added android_compose_ui_tooling_preview to the core and desig…
Halulkin Sep 18, 2023
b953607
Merge branch 'monstar-lab-oss:main' into main
Halulkin Nov 27, 2023
756f8cf
Merge branch 'main' into refator/modularisation
Halulkin Nov 27, 2023
d72285c
Merge pull request #73 from Halulkin/refator/modularisation
levinzonr Nov 27, 2023
96ed8c0
build: add material dep to the core module
levinzonr Nov 28, 2023
3fcb55b
build: Add AndroidAppConvetionPlugin and align java version using jav…
levinzonr Nov 28, 2023
098889e
style: apply spotless
levinzonr Nov 28, 2023
b763676
feat: add BuildConfiguration
levinzonr Nov 28, 2023
39cd96d
docs: update README
levinzonr Nov 28, 2023
90f95dd
docs: update README
levinzonr Nov 28, 2023
05167e4
refactor: rename corotuines related package in core
levinzonr Nov 28, 2023
a4abfa3
style: apply spotless
levinzonr Nov 28, 2023
215b45f
build: update dependencies kotlin 1.9.20, compose BOM, agp
levinzonr Nov 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/github-actions
Original file line number Diff line number Diff line change
@@ -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
52 changes: 21 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
30 changes: 10 additions & 20 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

@file:Suppress("UnstableApiUsage")
// TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed
@Suppress("DSL_SCOPE_VIOLATION")
Expand All @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -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")
}
Expand All @@ -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)
Expand All @@ -132,4 +120,6 @@ dependencies {
testImplementation(libs.bundles.test)
androidTestImplementation(libs.bundles.android.test)

implementation(project(":core"))
implementation(project(":designsystem"))
}
Original file line number Diff line number Diff line change
@@ -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)
}
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down
1 change: 1 addition & 0 deletions build-logic/convention/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
28 changes: 28 additions & 0 deletions build-logic/convention/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -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"
}
}
}
Original file line number Diff line number Diff line change
@@ -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<Project> {
override fun apply(target: Project) {
target.configure<ApplicationExtension> {
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()
}
}

}
}
Original file line number Diff line number Diff line change
@@ -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
}

Original file line number Diff line number Diff line change
@@ -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<Project> {
override fun apply(target: Project) {
with(target) {
extensions.configure<LibraryExtension> {
compileSdk = AndroidConfiguration.COMPILE_SDK
defaultConfig {
minSdk = AndroidConfiguration.MIN_SDK
}
buildFeatures {
compose = true
buildConfig = true
}
composeOptions {
kotlinCompilerExtensionVersion = target.rootProject.libs.findVersion("compose_compiler").get().toString()
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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<VersionCatalogsExtension>().named("libs")
4 changes: 4 additions & 0 deletions build-logic/gradle.properties
Original file line number Diff line number Diff line change
@@ -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
13 changes: 13 additions & 0 deletions build-logic/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
}
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}

include(":convention")
3 changes: 3 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions core/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
Loading
Loading