├── .github └── workflows │ └── ComposeFeaturedBasedMultiModule.yml ├── .gitignore ├── .idea ├── .gitignore ├── appInsightsSettings.xml ├── compiler.xml ├── deploymentTargetDropDown.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml ├── kotlinScripting.xml ├── kotlinc.xml ├── migrations.xml ├── misc.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle.kts ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── example │ │ └── composefeaturebasedmultimodule │ │ ├── MainApplication.kt │ │ ├── SingleActivity.kt │ │ └── ui │ │ └── theme │ │ ├── Color.kt │ │ ├── Theme.kt │ │ └── Type.kt │ └── res │ ├── drawable │ ├── ic_launcher_background.xml │ └── ic_launcher_foreground.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.webp │ └── ic_launcher_round.webp │ ├── mipmap-mdpi │ ├── ic_launcher.webp │ └── ic_launcher_round.webp │ ├── mipmap-xhdpi │ ├── ic_launcher.webp │ └── ic_launcher_round.webp │ ├── mipmap-xxhdpi │ ├── ic_launcher.webp │ └── ic_launcher_round.webp │ ├── mipmap-xxxhdpi │ ├── ic_launcher.webp │ └── ic_launcher_round.webp │ ├── values-night │ └── themes.xml │ ├── values │ ├── strings.xml │ └── themes.xml │ └── xml │ ├── backup_rules.xml │ └── data_extraction_rules.xml ├── build.gradle.kts ├── core ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── example │ └── core │ ├── components │ ├── CoilImageComponent.kt │ ├── ErrorComponent.kt │ └── LoadingComponent.kt │ ├── di │ └── CoroutineModule.kt │ ├── model │ └── GenericException.kt │ ├── navigation │ └── NavigationService.kt │ ├── presentation │ └── StateAndEventViewModel.kt │ └── utils │ ├── Constants.kt │ └── Qualifiers.kt ├── detail ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ └── com │ │ └── example │ │ └── detail │ │ ├── data │ │ ├── api │ │ │ ├── DetailApi.kt │ │ │ ├── datasource │ │ │ │ ├── DetailDataSource.kt │ │ │ │ └── DetailDataSourceImpl.kt │ │ │ ├── di │ │ │ │ └── DataSourceModule.kt │ │ │ └── model │ │ │ │ └── ItemDetailResponse.kt │ │ └── domain_impl │ │ │ ├── di │ │ │ └── UseCaseModule.kt │ │ │ ├── mapper │ │ │ └── ItemDetailMapper.kt │ │ │ └── usecase │ │ │ └── GetItemDetailUseCaseImpl.kt │ │ ├── domain │ │ ├── model │ │ │ └── ItemDetail.kt │ │ └── usecase │ │ │ └── GetItemDetailUseCase.kt │ │ └── presentation │ │ ├── DetailScreen.kt │ │ ├── DetailSearchScreen.kt │ │ ├── DetailViewModel.kt │ │ ├── components │ │ └── DetailContent.kt │ │ ├── state │ │ └── DetailUIState.kt │ │ └── uievent │ │ └── DetailUIEvent.kt │ └── test │ └── java │ └── com │ └── example │ └── detail │ ├── data │ ├── datasource │ │ └── DetailDataSourceTest.kt │ └── domainimpl │ │ └── GetItemDetailUseCaseTest.kt │ └── presentation │ └── DetailViewModelTest.kt ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── home ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── example │ └── home │ ├── data │ ├── api │ │ ├── HomeApi.kt │ │ ├── datasource │ │ │ ├── HomeDataSource.kt │ │ │ └── HomeDataSourceImpl.kt │ │ ├── di │ │ │ └── DataSourceModule.kt │ │ └── model │ │ │ └── HomeResponse.kt │ └── domainimpl │ │ ├── di │ │ └── UseCaseModule.kt │ │ ├── mapper │ │ └── HomeSectionsMapper.kt │ │ └── usecase │ │ └── GetInitialHomeUseCaseImpl.kt │ ├── domain │ ├── model │ │ ├── BannerItem.kt │ │ ├── CatalogItem.kt │ │ ├── HomeSections.kt │ │ └── ProductItem.kt │ └── usecase │ │ └── GetInitialHomeUseCase.kt │ └── presentation │ ├── HomeScreen.kt │ ├── HomeViewModel.kt │ ├── components │ ├── DetailBottomSheet.kt │ ├── HomeScreenContent.kt │ ├── SectionList.kt │ └── VerticalItemCard.kt │ ├── sections │ ├── BannerSection.kt │ ├── SectionTitle.kt │ └── SlidableSection.kt │ ├── state │ └── HomeUIState.kt │ └── uievent │ └── HomeUIEvent.kt ├── lint.xml ├── list ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── example │ └── list │ ├── data │ ├── api │ │ ├── ListApi.kt │ │ ├── datasource │ │ │ ├── ListDataSource.kt │ │ │ └── ListDataSourceImpl.kt │ │ ├── di │ │ │ └── DataSourceModule.kt │ │ └── model │ │ │ └── ListResponse.kt │ └── domain_impl │ │ ├── di │ │ └── UseCaseModule.kt │ │ ├── mapper │ │ └── ListDataMapper.kt │ │ └── usecase │ │ └── GetListUseCaseImpl.kt │ ├── domain │ ├── model │ │ └── ListData.kt │ └── usecase │ │ └── GetListUseCase.kt │ └── presentation │ ├── ListScreen.kt │ ├── ListViewModel.kt │ ├── components │ └── ListContent.kt │ ├── event │ └── ListUIEvent.kt │ └── state │ └── ListUIState.kt ├── navigation ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── example │ └── navigation │ ├── AppNavigation.kt │ ├── Destination.kt │ ├── Navigator.kt │ ├── di │ └── NavigationModule.kt │ ├── graph │ ├── DetailGraph.kt │ ├── DetailGraphBuilder.kt │ ├── DetailMain.kt │ └── DetailSearch.kt │ ├── screens │ ├── Detail.kt │ ├── Home.kt │ └── List.kt │ └── utils │ ├── ArgsScreen.kt │ ├── NavigationDestination.kt │ ├── NavigationGraph.kt │ ├── NodeScreen.kt │ └── WithoutArgsScreen.kt ├── network ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── example │ └── network │ ├── di │ └── NetworkModule.kt │ └── extensions │ └── ApiHelper.kt └── settings.gradle.kts /.github/workflows/ComposeFeaturedBasedMultiModule.yml: -------------------------------------------------------------------------------- 1 | name: ComposeFeatureBasedMultiModule CI Workflow 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout Repository 15 | uses: actions/checkout@v2 16 | 17 | - name: Setup Java JDK 18 | uses: actions/setup-java@v3.13.0 19 | with: 20 | java-version: '18' 21 | distribution: 'adopt' 22 | 23 | - name: Build with Gradle 24 | run: ./gradlew build 25 | 26 | - name: Run Tests 27 | run: ./gradlew test 28 | 29 | - name: Upload a Build Artifact 30 | uses: actions/upload-artifact@v3.1.3 31 | with: 32 | name: ComposeFeatureBasedMultiModule.apk 33 | path: app/build/outputs/apk/debug/app-debug.apk 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/appInsightsSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 44 | 45 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/deploymentTargetDropDown.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 24 | 25 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 41 | -------------------------------------------------------------------------------- /.idea/kotlinScripting.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/migrations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Project Descriptions 2 | 3 | # Why and What is the aim? 4 | 5 | This project aims to demonstrate a feature-based modularization by managing the inter-feature dependencies through a dedicated navigation module and draws inspiration from Hexagonal Architecture and Clean Architecture to isolate the core of the application (domain logic or business logic) from other factors, allowing for a more flexible and decoupled system design. 6 | ![1](https://github.com/basaransuleyman/suleyman-basaranoglu-json/blob/main/Appflow.png) 7 | 8 | # Architecture Opinion 9 | 10 | In addition, the project adopts a Hexagonal Architecture ( Use Case -(Adapter) & Use Case(Port) ) with a Clean Architecture ( Data - Domain - Presentation like in an SS at Feature Module - `home` ). By establishing domain implementation (domain-impl) as the adapter that connects to the domain port, the project leverages certain aspects of various architectural patterns without being strictly bound to any single one. This hybrid approach allows the application to benefit from the strengths of different architectures while maintaining the flexibility to adapt to specific project needs. 11 | 12 | With this opinion, the domain layer has a sole dependency on domain-impl. Within the data layer, structures like API and persistence are focused solely on their respective operations. The dependency of the domain on the data layer is mitigated through the use of mappers within the domain-impl. These mappers transform data responses into domain entities, thus decoupling the domain logic from the specifics of the data source implementations. This is a strategic design choice that preserves the purity of the domain layer, allowing it to evolve independently of the data layer changes and maintaining the domain model's integrity. 13 | 14 | ![1](https://github.com/basaransuleyman/suleyman-basaranoglu-json/blob/main/Hexo.png) 15 | 16 | **The main rule and our goal is, to isolate the core of the application (domain logic or business logic) from other factors, Hexagonal Architecture and Clean Architecture are just tools for us, we are trying to use the places that are suitable for us here by taking advantage of both.** 17 | 18 | # Module Descriptions 19 | 20 | ## Feature Module - `home` 21 | ![1](https://github.com/basaransuleyman/suleyman-basaranoglu-json/blob/main/Home.png) 22 | 23 | Each feature module is divided into data, domain, and presentation layers. The data layer is further divided into API, DomainImpl and Persistence. The main reason for this distinction is the principle of single responsibility and the management of the resource from a single point. For example, while the API module is only responsible for communicating with remote services, with domainimpl we prevent the dependency of the domain layer on the API layer. 24 | This structure shows how an Android application can be developed in a sustainable and scalable way, inspired by architectural principles such as Clean Architecture and Hexagonal Architecture ( Like Adapter is domain-impl and port is domain). 25 | 26 | 27 | ### Advantages: 28 | - **Single-Stop Management of Resources:** Managing data and functions from a central point provides consistency and order within the system. 29 | - **Independence Between Layers:** Thanks to the independence between layers, it is possible to develop each module on its own without being affected by changes. 30 | - **Modularity:** Since the system has a modular structure, it is easier to integrate new features or changes. 31 | - **Testability:** The independence of each layer makes testing processes more efficient and focused. 32 | 33 | ### Disadvantages: 34 | - **Configuration Complexity:** The multitude of layers and modules. 35 | - **Dependency Management:** Maintaining the independence of each module can become difficult as the project grows. 36 | 37 | ## Navigation Module - `navigation` 38 | ![1](https://github.com/basaransuleyman/suleyman-basaranoglu-json/blob/main/navigation-module.png) 39 | 40 | This module orchestrates the screen transitions and manages the navigation routes within the app. The Navigator class is equipped with functions that facilitate navigation to different screens, while AppNavigation is responsible for setting up the navigation routes. Crucially, the Navigation module operates independently of other modules, which plays a key role in decoupling feature modules from one another. This means that individual features do not have direct knowledge of each other, and all inter-feature navigation is coordinated through the Navigation module. 41 | 42 | ### Navigation Flow: 43 | ![1](https://github.com/basaransuleyman/suleyman-basaranoglu-json/blob/main/navflow.png) 44 | 45 | ### Advantages: 46 | 47 | - **Decoupling of Feature Modules:** The Navigation module's independence ensures that feature modules do not depend on each other, allowing for more modular and interchangeable components within the application. 48 | - **Centralized Navigation Handling:** A dedicated class for navigation streamlines all navigation-related logic into a single, manageable location. 49 | - **Separation of Concerns:** AppNavigation focuses exclusively on route configuration, allowing Navigator to handle the execution of navigation commands without interference. 50 | - **Flexibility:** Supports dynamic navigation flows and is readily extensible to incorporate new features or screens, catering to the evolving needs of the application. 51 | 52 | ### Disadvantages: 53 | 54 | - **Documentation:** Without well-documented argument-passing systems, may find it challenging to grasp the navigation logic. 55 | 56 | ### Concerns: 57 | - **Startup Time:** While @Composable screen functions are only invoked when necessary, the impact on the app's startup time can vary depending on project complexity and screen content it needs to be tried with its project. 58 | 59 | ### Screen Adding Mechanism: 60 | 61 | ![1](https://github.com/basaransuleyman/suleyman-basaranoglu-json/blob/main/AppNavigation.png) 62 | 63 | 64 | ## Network Module - `network` 65 | 66 | The Network Module is a critical component of the architecture, encompassing all aspects of networking logic. It's crafted to function independently, sourcing its constants from the core module while remaining detached from other modules. 67 | 68 | ### Advantages : 69 | 70 | - **Isolation:** Isolating network operations allows the rest of the application to be indifferent to the data's origin, whether it's fetched from a remote server or local database. 71 | - **Single Responsibility:** Dedicated to network transactions, the module serves as a centralized point for implementing changes related to network operations. 72 | - **Reusability:** With consistent data contracts, the Network Module can be repurposed across various projects or features within the same project. 73 | 74 | ### Disadvantages : 75 | 76 | - **Modular Overhead:** An extensive number of modules can introduce complexity in the build configuration and may lead to longer build times. 77 | - **Dependency Management:** Ensuring that the Network Module remains fully decoupled requires meticulous management of dependencies, which can be challenging as the project grows. 78 | 79 | ### Dependencies Flow 80 | 81 | ![1](https://github.com/basaransuleyman/suleyman-basaranoglu-json/blob/main/correctDependencies.png) 82 | 83 | ### E2E Unit Test - Detail Module 84 | 85 | ![1](https://github.com/basaransuleyman/suleyman-basaranoglu-json/blob/main/detaile2etest.png) 86 | 87 | ## App Screens: 88 | 89 | ![1](https://github.com/basaransuleyman/suleyman-basaranoglu-json/blob/main/dynamichome.png) 90 | ![1](https://github.com/basaransuleyman/suleyman-basaranoglu-json/blob/main/detailhomes.png) 91 | ![1](https://github.com/basaransuleyman/suleyman-basaranoglu-json/blob/main/listpages.png) 92 | 93 | 94 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.application") 3 | id("org.jetbrains.kotlin.android") 4 | id(libs.plugins.daggerHilt.get().toString()) 5 | id(libs.plugins.ksp.get().toString()) 6 | } 7 | 8 | android { 9 | namespace = libs.plugins.mainNamespace.get().toString() 10 | compileSdk = libs.versions.compileSdk.get().toInt() 11 | 12 | defaultConfig { 13 | applicationId = libs.plugins.mainNamespace.get().toString() 14 | minSdk = libs.versions.minSdk.get().toInt() 15 | targetSdk =libs.versions.compileSdk.get().toInt() 16 | versionCode = 1 17 | versionName = "1.0" 18 | vectorDrawables { 19 | useSupportLibrary = true 20 | } 21 | } 22 | 23 | 24 | compileOptions { 25 | sourceCompatibility = JavaVersion.VERSION_1_8 26 | targetCompatibility = JavaVersion.VERSION_1_8 27 | } 28 | kotlinOptions { 29 | jvmTarget = libs.versions.jvmTarget.get() 30 | } 31 | buildFeatures { 32 | compose = true 33 | } 34 | composeOptions { 35 | kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerVersion.get() 36 | } 37 | packaging { 38 | resources { 39 | excludes += "/META-INF/{AL2.0,LGPL2.1}" 40 | } 41 | } 42 | } 43 | 44 | dependencies { 45 | implementation(project(":navigation")) 46 | implementation(project(":core")) 47 | implementation(project(":home"))// just home Compose Screen 48 | implementation(project(":list")) // just list Compose Screen 49 | implementation(project(":detail")) // just list Compose Screen 50 | implementation(project(":network")) 51 | 52 | //region D.I Dependencies 53 | ksp(libs.hilt.compiler) 54 | ksp(libs.hilt.ksp.compiler) 55 | implementation(libs.hilt.core) 56 | //endregion 57 | 58 | //region Compose Dependencies 59 | implementation(libs.compose.activity) 60 | implementation(platform(libs.compose.bom)) 61 | implementation(libs.ui) 62 | implementation(libs.compose.ui.graphics) 63 | implementation(libs.ui.tooling.preview) 64 | implementation(libs.compose.ui.material) 65 | androidTestImplementation(platform(libs.compose.bom)) 66 | //endregion 67 | 68 | //region Core Dependencies 69 | implementation(libs.appcompat) 70 | implementation(libs.android.core) 71 | //endregion 72 | 73 | implementation(libs.lifecycle.ktx) 74 | 75 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/composefeaturebasedmultimodule/MainApplication.kt: -------------------------------------------------------------------------------- 1 | package com.example.composefeaturebasedmultimodule 2 | 3 | import android.app.Application 4 | import dagger.hilt.android.HiltAndroidApp 5 | 6 | @HiltAndroidApp 7 | class MainApplication: Application() -------------------------------------------------------------------------------- /app/src/main/java/com/example/composefeaturebasedmultimodule/SingleActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.composefeaturebasedmultimodule 2 | 3 | import android.os.Bundle 4 | import androidx.activity.ComponentActivity 5 | import androidx.activity.compose.setContent 6 | import com.example.composefeaturebasedmultimodule.ui.theme.ComposeFeatureBasedMultiModuleTheme 7 | import com.example.detail.presentation.DetailScreen 8 | import com.example.detail.presentation.DetailSearchScreen 9 | import com.example.home.presentation.HomeScreen 10 | import com.example.list.presentation.ListScreen 11 | import com.example.navigation.AppNavigation 12 | import com.example.navigation.Navigator 13 | import com.example.navigation.graph.DetailScreens 14 | import dagger.hilt.android.AndroidEntryPoint 15 | import javax.inject.Inject 16 | 17 | @AndroidEntryPoint 18 | class SingleActivity : ComponentActivity() { 19 | 20 | @Inject 21 | lateinit var navigator: Navigator 22 | 23 | override fun onCreate(savedInstanceState: Bundle?) { 24 | super.onCreate(savedInstanceState) 25 | setContent { 26 | ComposeFeatureBasedMultiModuleTheme { 27 | AppNavigation( 28 | navigator = navigator, 29 | homeScreen = { 30 | HomeScreen() 31 | }, 32 | listScreen = { 33 | ListScreen() 34 | }, 35 | detailScreen = {// We can get args with "it" if we need 36 | DetailScreen() 37 | }, 38 | detailScreenWithGraph = DetailScreens( 39 | detailMain = { DetailScreen() }, 40 | detailSearch = { DetailSearchScreen() } 41 | ) 42 | ) 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/composefeaturebasedmultimodule/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package com.example.composefeaturebasedmultimodule.ui.theme 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | val Purple80 = Color(0xFFD0BCFF) 6 | val PurpleGrey80 = Color(0xFFCCC2DC) 7 | val Pink80 = Color(0xFFEFB8C8) 8 | 9 | val Purple40 = Color(0xFF6650a4) 10 | val PurpleGrey40 = Color(0xFF625b71) 11 | val Pink40 = Color(0xFF7D5260) -------------------------------------------------------------------------------- /app/src/main/java/com/example/composefeaturebasedmultimodule/ui/theme/Theme.kt: -------------------------------------------------------------------------------- 1 | package com.example.composefeaturebasedmultimodule.ui.theme 2 | 3 | import android.app.Activity 4 | import android.os.Build 5 | import androidx.compose.foundation.isSystemInDarkTheme 6 | import androidx.compose.material3.MaterialTheme 7 | import androidx.compose.material3.darkColorScheme 8 | import androidx.compose.material3.dynamicDarkColorScheme 9 | import androidx.compose.material3.dynamicLightColorScheme 10 | import androidx.compose.material3.lightColorScheme 11 | import androidx.compose.runtime.Composable 12 | import androidx.compose.runtime.SideEffect 13 | import androidx.compose.ui.graphics.toArgb 14 | import androidx.compose.ui.platform.LocalContext 15 | import androidx.compose.ui.platform.LocalView 16 | import androidx.core.view.WindowCompat 17 | 18 | private val DarkColorScheme = darkColorScheme( 19 | primary = Purple80, 20 | secondary = PurpleGrey80, 21 | tertiary = Pink80 22 | ) 23 | 24 | private val LightColorScheme = lightColorScheme( 25 | primary = Purple40, 26 | secondary = PurpleGrey40, 27 | tertiary = Pink40 28 | 29 | /* Other default colors to override 30 | background = Color(0xFFFFFBFE), 31 | surface = Color(0xFFFFFBFE), 32 | onPrimary = Color.White, 33 | onSecondary = Color.White, 34 | onTertiary = Color.White, 35 | onBackground = Color(0xFF1C1B1F), 36 | onSurface = Color(0xFF1C1B1F), 37 | */ 38 | ) 39 | 40 | @Composable 41 | fun ComposeFeatureBasedMultiModuleTheme( 42 | darkTheme: Boolean = isSystemInDarkTheme(), 43 | // Dynamic color is available on Android 12+ 44 | dynamicColor: Boolean = true, 45 | content: @Composable () -> Unit 46 | ) { 47 | val colorScheme = when { 48 | dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { 49 | val context = LocalContext.current 50 | if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) 51 | } 52 | 53 | darkTheme -> DarkColorScheme 54 | else -> LightColorScheme 55 | } 56 | val view = LocalView.current 57 | if (!view.isInEditMode) { 58 | SideEffect { 59 | val window = (view.context as Activity).window 60 | window.statusBarColor = colorScheme.primary.toArgb() 61 | WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme 62 | } 63 | } 64 | 65 | MaterialTheme( 66 | colorScheme = colorScheme, 67 | typography = Typography, 68 | content = content 69 | ) 70 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/composefeaturebasedmultimodule/ui/theme/Type.kt: -------------------------------------------------------------------------------- 1 | package com.example.composefeaturebasedmultimodule.ui.theme 2 | 3 | import androidx.compose.material3.Typography 4 | import androidx.compose.ui.text.TextStyle 5 | import androidx.compose.ui.text.font.FontFamily 6 | import androidx.compose.ui.text.font.FontWeight 7 | import androidx.compose.ui.unit.sp 8 | 9 | // Set of Material typography styles to start with 10 | val Typography = Typography( 11 | bodyLarge = TextStyle( 12 | fontFamily = FontFamily.Default, 13 | fontWeight = FontWeight.Normal, 14 | fontSize = 16.sp, 15 | lineHeight = 24.sp, 16 | letterSpacing = 0.5.sp 17 | ) 18 | /* Other default text styles to override 19 | titleLarge = TextStyle( 20 | fontFamily = FontFamily.Default, 21 | fontWeight = FontWeight.Normal, 22 | fontSize = 22.sp, 23 | lineHeight = 28.sp, 24 | letterSpacing = 0.sp 25 | ), 26 | labelSmall = TextStyle( 27 | fontFamily = FontFamily.Default, 28 | fontWeight = FontWeight.Medium, 29 | fontSize = 11.sp, 30 | lineHeight = 16.sp, 31 | letterSpacing = 0.5.sp 32 | ) 33 | */ 34 | ) -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basaransuleyman/Compose-FeatureBase-Multi-Module-Clean-Hexagonal-Architecture-Android-Kotlin/d951d3c552e2ba949244c70b9e2f012c4e03c866/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basaransuleyman/Compose-FeatureBase-Multi-Module-Clean-Hexagonal-Architecture-Android-Kotlin/d951d3c552e2ba949244c70b9e2f012c4e03c866/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basaransuleyman/Compose-FeatureBase-Multi-Module-Clean-Hexagonal-Architecture-Android-Kotlin/d951d3c552e2ba949244c70b9e2f012c4e03c866/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basaransuleyman/Compose-FeatureBase-Multi-Module-Clean-Hexagonal-Architecture-Android-Kotlin/d951d3c552e2ba949244c70b9e2f012c4e03c866/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basaransuleyman/Compose-FeatureBase-Multi-Module-Clean-Hexagonal-Architecture-Android-Kotlin/d951d3c552e2ba949244c70b9e2f012c4e03c866/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basaransuleyman/Compose-FeatureBase-Multi-Module-Clean-Hexagonal-Architecture-Android-Kotlin/d951d3c552e2ba949244c70b9e2f012c4e03c866/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basaransuleyman/Compose-FeatureBase-Multi-Module-Clean-Hexagonal-Architecture-Android-Kotlin/d951d3c552e2ba949244c70b9e2f012c4e03c866/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basaransuleyman/Compose-FeatureBase-Multi-Module-Clean-Hexagonal-Architecture-Android-Kotlin/d951d3c552e2ba949244c70b9e2f012c4e03c866/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basaransuleyman/Compose-FeatureBase-Multi-Module-Clean-Hexagonal-Architecture-Android-Kotlin/d951d3c552e2ba949244c70b9e2f012c4e03c866/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basaransuleyman/Compose-FeatureBase-Multi-Module-Clean-Hexagonal-Architecture-Android-Kotlin/d951d3c552e2ba949244c70b9e2f012c4e03c866/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ComposeFeatureBasedMultiModule 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 |