├── .editorconfig ├── .gitignore ├── AndroidRealCA-Modules.png ├── README.md ├── app ├── .gitignore ├── build.gradle.kts ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ ├── App.kt │ │ ├── MainActivity.kt │ │ ├── di │ │ ├── AndroidCacheProvider.kt │ │ └── Injector.kt │ │ └── navigation │ │ └── RootNavigation.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 │ ├── colors.xml │ ├── strings.xml │ └── themes.xml │ └── xml │ ├── backup_rules.xml │ └── data_extraction_rules.xml ├── build.gradle.kts ├── cache-test ├── .gitignore ├── build.gradle.kts └── src │ └── commonMain │ └── kotlin │ └── com │ └── denisbrandi │ └── androidrealca │ └── cache │ └── test │ ├── InMemoryCachedObject.kt │ └── TestCacheProvider.kt ├── cache ├── .gitignore ├── build.gradle.kts └── src │ ├── commonMain │ └── kotlin │ │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── cache │ │ ├── CacheProvider.kt │ │ ├── CachedObject.kt │ │ ├── FlowCachedObject.kt │ │ ├── RealCachedObject.kt │ │ └── RealFlowCachedObject.kt │ └── commonTest │ └── kotlin │ └── com │ └── denisbrandi │ └── androidrealca │ └── cache │ ├── RealCachedObjectTest.kt │ ├── RealFlowCachedObjectTest.kt │ └── fixture │ └── TestModel.kt ├── cart-component ├── .gitignore ├── build.gradle.kts └── src │ ├── commonMain │ └── kotlin │ │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── cart │ │ ├── data │ │ ├── model │ │ │ └── JsonCartCacheDto.kt │ │ └── repository │ │ │ └── RealCartRepository.kt │ │ ├── di │ │ └── CartComponentDI.kt │ │ └── domain │ │ ├── model │ │ ├── Cart.kt │ │ └── CartItem.kt │ │ ├── repository │ │ └── CartRepository.kt │ │ └── usecase │ │ ├── AddCartItemUseCase.kt │ │ ├── CartUseCases.kt │ │ ├── ObserveUserCartUseCase.kt │ │ └── UpdateCartItemUseCase.kt │ └── commonTest │ └── kotlin │ └── com │ └── denisbrandi │ └── androidrealca │ └── cart │ ├── data │ └── repository │ │ └── RealCartRepositoryTest.kt │ └── domain │ ├── model │ ├── CartItemFixture.kt │ └── CartTest.kt │ ├── repository │ └── TestCartRepository.kt │ └── usecase │ ├── AddCartItemUseCaseTest.kt │ ├── ObserveUserCartUseCaseTest.kt │ └── UpdateCartItemUseCaseTest.kt ├── cart-ui ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── debug │ └── screenshotTest │ │ └── reference │ │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── cart │ │ └── presentation │ │ └── view │ │ └── CartScreenPreviewsKt │ │ ├── PreviewPLPEmptyState_0.png │ │ └── PreviewPLPProductsState_0.png │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── denisbrandi │ │ │ └── androidrealca │ │ │ └── cart │ │ │ ├── di │ │ │ └── CartUIDI.kt │ │ │ └── presentation │ │ │ ├── view │ │ │ └── CartScreen.kt │ │ │ └── viewmodel │ │ │ ├── CartViewModel.kt │ │ │ └── RealCartViewModel.kt │ └── res │ │ ├── drawable │ │ ├── baseline_add_24.xml │ │ └── baseline_remove_24.xml │ │ └── values │ │ └── strings.xml │ ├── screenshotTest │ └── kotlin │ │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── cart │ │ └── presentation │ │ └── view │ │ ├── CartScreenPreviews.kt │ │ └── PreviewFixtures.kt │ └── test │ └── java │ └── com │ └── denisbrandi │ └── androidrealca │ └── cart │ └── presentation │ └── viewmodel │ └── RealCartViewModelTest.kt ├── coroutines-test-dispatcher ├── .gitignore ├── build.gradle.kts └── src │ └── main │ └── java │ └── com │ └── denisbrandi │ └── androidrealca │ └── coroutines │ └── testdispatcher │ └── MainCoroutineRule.kt ├── coverage ├── androidCoverageReport.gradle ├── kmpCoverageReport.gradle └── overallCoverageReport.gradle ├── designsystem ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── designsystem │ │ ├── Buttons.kt │ │ ├── Colors.kt │ │ ├── Dimens.kt │ │ ├── EmptyContents.kt │ │ ├── ErrorDialogs.kt │ │ ├── ErrorViews.kt │ │ ├── Labels.kt │ │ ├── Loadings.kt │ │ ├── ModalEvent.kt │ │ ├── Theme.kt │ │ ├── TopBar.kt │ │ └── Typography.kt │ └── res │ ├── drawable │ ├── baseline_add_shopping_cart_24.xml │ └── baseline_image_24.xml │ └── values │ └── string.xml ├── flow-test-observer ├── .gitignore ├── build.gradle.kts └── src │ └── commonMain │ └── kotlin │ └── com │ └── denisbrandi │ └── androidrealca │ └── flow │ └── testobserver │ └── FlowTestObserver.kt ├── foundations ├── .gitignore ├── build.gradle.kts └── src │ ├── commonMain │ └── kotlin │ │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── foundations │ │ └── Answer.kt │ └── commonTest │ └── kotlin │ └── com │ └── denisbrandi │ └── androidrealca │ └── foundations │ └── AnswerTest.kt ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── httpclient ├── .gitignore ├── build.gradle.kts └── src │ ├── commonMain │ └── kotlin │ │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── httpclient │ │ ├── AccessTokenProvider.kt │ │ ├── HttpClientProvider.kt │ │ └── RealHttpClientProvider.kt │ └── commonTest │ └── kotlin │ └── com │ └── denisbrandi │ └── androidrealca │ └── httpclient │ └── AccessTokenProviderTest.kt ├── main-ui ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── debug │ └── screenshotTest │ │ └── reference │ │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── main │ │ └── presentation │ │ └── view │ │ └── MainScreenPreviewsKt │ │ ├── PreviewCartBadgeState_0.png │ │ └── PreviewNoBadgesState_0.png │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── denisbrandi │ │ │ └── androidrealca │ │ │ └── main │ │ │ ├── di │ │ │ └── MainUIDI.kt │ │ │ └── presentation │ │ │ ├── view │ │ │ └── MainScreen.kt │ │ │ └── viewmodel │ │ │ ├── MainViewModel.kt │ │ │ └── RealMainViewModel.kt │ └── res │ │ └── values │ │ └── strings.xml │ ├── screenshotTest │ └── kotlin │ │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── main │ │ └── presentation │ │ └── view │ │ └── MainScreenPreviews.kt │ └── test │ └── java │ └── com │ └── denisbrandi │ └── androidrealca │ └── main │ └── presentation │ └── viewmodel │ └── RealMainViewModelTest.kt ├── money-component ├── .gitignore ├── build.gradle.kts └── src │ └── commonMain │ └── kotlin │ └── com │ └── denisbrandi │ └── androidrealca │ └── money │ └── domain │ └── model │ └── Money.kt ├── money-ui ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── money │ │ └── presentation │ │ ├── presenter │ │ └── MoneyPresenter.kt │ │ └── view │ │ └── PriceText.kt │ └── test │ └── java │ └── com │ └── denisbrandi │ └── androidrealca │ └── money │ └── presentation │ └── presenter │ └── MoneyPresenterTest.kt ├── onboarding-ui ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── debug │ └── screenshotTest │ │ └── reference │ │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── onboarding │ │ └── presentation │ │ └── view │ │ └── LoginScreenPreviewsKt │ │ ├── PreviewLoginScreenFormState_0.png │ │ └── PreviewLoginScreenLoggingInState_0.png │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── denisbrandi │ │ │ └── androidrealca │ │ │ └── onboarding │ │ │ ├── di │ │ │ └── OnboardingUIDI.kt │ │ │ └── presentation │ │ │ ├── view │ │ │ └── LoginScreen.kt │ │ │ └── viewmodel │ │ │ ├── LoginViewModel.kt │ │ │ └── RealLoginViewModel.kt │ └── res │ │ └── values │ │ └── strings.xml │ ├── screenshotTest │ └── kotlin │ │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── onboarding │ │ └── presentation │ │ └── view │ │ └── LoginScreenPreviews.kt │ └── test │ └── java │ └── com │ └── denisbrandi │ └── androidrealca │ └── onboarding │ └── presentation │ └── viewmodel │ └── RealLoginViewModelTest.kt ├── plp-ui ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── debug │ └── screenshotTest │ │ └── reference │ │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── plp │ │ └── presentation │ │ └── view │ │ └── PLPScreenPreviewsKt │ │ ├── PreviewPLPDefaultState_0.png │ │ ├── PreviewPLPEmptyState_0.png │ │ ├── PreviewPLPErrorState_0.png │ │ ├── PreviewPLPLoadingState_0.png │ │ └── PreviewPLPProductsState_0.png │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── denisbrandi │ │ │ └── androidrealca │ │ │ └── plp │ │ │ ├── di │ │ │ └── PLPUIDI.kt │ │ │ └── presentation │ │ │ ├── view │ │ │ └── PLPScreen.kt │ │ │ └── viewmodel │ │ │ ├── PLPViewModel.kt │ │ │ └── RealPLPViewModel.kt │ └── res │ │ ├── drawable │ │ ├── baseline_favorite_24.xml │ │ └── baseline_favorite_border_24.xml │ │ └── values │ │ └── strings.xml │ ├── screenshotTest │ └── kotlin │ │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── plp │ │ └── presentation │ │ └── view │ │ ├── PLPScreenPreviews.kt │ │ └── PreviewFixtures.kt │ └── test │ └── java │ └── com │ └── denisbrandi │ └── androidrealca │ └── plp │ └── presentation │ └── viewmodel │ └── RealPLPViewModelTest.kt ├── product-component ├── .gitignore ├── build.gradle.kts └── src │ ├── commonMain │ └── kotlin │ │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── product │ │ ├── data │ │ ├── model │ │ │ └── JsonProductResponseDTO.kt │ │ └── repository │ │ │ └── RealProductRepository.kt │ │ ├── di │ │ └── ProductComponentDI.kt │ │ └── domain │ │ ├── model │ │ └── Product.kt │ │ ├── repository │ │ └── ProductRepository.kt │ │ └── usecase │ │ └── GetProducts.kt │ └── commonTest │ └── kotlin │ └── com │ └── denisbrandi │ └── androidrealca │ └── product │ └── data │ └── repository │ └── RealProductRepositoryTest.kt ├── scripts ├── installKtlint.sh ├── ktlintCheck.sh ├── ktlintFormat.sh └── runAllTests.sh ├── settings.gradle.kts ├── user-component ├── .gitignore ├── build.gradle.kts └── src │ ├── commonMain │ └── kotlin │ │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── user │ │ ├── data │ │ ├── model │ │ │ ├── JsonLoginRequestDTO.kt │ │ │ ├── JsonLoginResponseDTO.kt │ │ │ └── JsonUserCacheDTO.kt │ │ └── repository │ │ │ └── RealUserRepository.kt │ │ ├── di │ │ └── UserComponentDI.kt │ │ └── domain │ │ ├── model │ │ ├── Email.kt │ │ ├── LoginError.kt │ │ ├── LoginRequest.kt │ │ ├── Password.kt │ │ └── User.kt │ │ ├── repository │ │ └── UserRepository.kt │ │ └── usecase │ │ ├── LoginUseCase.kt │ │ └── UserUseCases.kt │ └── commonTest │ └── kotlin │ └── com │ └── denisbrandi │ └── androidrealca │ └── user │ ├── data │ └── repository │ │ └── RealUserRepositoryTest.kt │ └── domain │ ├── model │ ├── EmailTest.kt │ └── PasswordTest.kt │ ├── repository │ └── TestUserRepository.kt │ └── usecase │ └── LoginUseCaseTest.kt ├── viewmodel ├── .gitignore ├── build.gradle.kts └── src │ └── commonMain │ └── kotlin │ └── com │ └── denisbrandi │ └── androidrealca │ └── viewmodel │ └── ViewModel.kt ├── wishlist-component ├── .gitignore ├── build.gradle.kts └── src │ ├── commonMain │ └── kotlin │ │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── wishlist │ │ ├── data │ │ ├── model │ │ │ └── JsonWishlistCacheDto.kt │ │ └── repository │ │ │ └── RealWishlistRepository.kt │ │ ├── di │ │ └── WishlistComponentDI.kt │ │ └── domain │ │ ├── model │ │ └── WishlistItem.kt │ │ ├── repository │ │ └── WishlistRepository.kt │ │ └── usecase │ │ ├── AddToWishlistUseCase.kt │ │ ├── ObserveUserWishlistIdsUseCase.kt │ │ ├── ObserveUserWishlistUseCase.kt │ │ ├── RemoveFromWishlistUseCase.kt │ │ └── WishlistUseCases.kt │ └── commonTest │ └── kotlin │ └── com │ └── denisbrandi │ └── androidrealca │ └── wishlist │ ├── data │ └── repository │ │ └── RealWishlistRepositoryTest.kt │ └── domain │ ├── model │ └── WishlistItemFixtures.kt │ ├── repository │ └── TestWishlistRepository.kt │ └── usecase │ ├── AddToWishlistUseCaseTest.kt │ ├── ObserveUserWishlistIdsUseCaseTest.kt │ ├── ObserveUserWishlistTest.kt │ └── RemoveFromWishlistUseCaseTest.kt └── wishlist-ui ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src ├── debug └── screenshotTest │ └── reference │ └── com │ └── denisbrandi │ └── androidrealca │ └── wishlist │ └── presentation │ └── view │ └── WishlistScreenPreviewsKt │ ├── PreviewPLPEmptyState_0.png │ └── PreviewPLPProductsState_0.png ├── main ├── AndroidManifest.xml ├── java │ └── com │ │ └── denisbrandi │ │ └── androidrealca │ │ └── wishlist │ │ ├── di │ │ └── WishlistUIDI.kt │ │ └── presentation │ │ ├── view │ │ └── WishlistScreen.kt │ │ └── viewmodel │ │ ├── RealWishlistViewModel.kt │ │ └── WishlistViewModel.kt └── res │ ├── drawable │ └── baseline_delete_24.xml │ └── values │ └── strings.xml ├── screenshotTest └── kotlin │ └── com │ └── denisbrandi │ └── androidrealca │ └── wishlist │ └── presentation │ └── view │ ├── PreviewFixtures.kt │ └── WishlistScreenPreviews.kt └── test └── java └── com └── denisbrandi └── androidrealca └── wishlist └── presentation └── viewmodel └── RealWishlistViewModelTest.kt /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | root = true 3 | [*] 4 | indent_style = space 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | [*.{java,kt,kts,scala,rs,xml,kt.spec,kts.spec}] 10 | indent_size = 4 11 | [*.{kt,kts}] 12 | ktlint_code_style = android_studio 13 | ij_kotlin_imports_layout = * 14 | ij_kotlin_allow_trailing_comma = false 15 | ij_kotlin_allow_trailing_comma_on_call_site = false 16 | # General 17 | ktlint_standard_no-wildcard-imports = disabled 18 | ktlint_standard_trailing-comma-on-declaration-site = disabled 19 | ktlint_standard_trailing-comma-on-call-site = disabled 20 | ktlint_standard_max-line-length = disabled 21 | ktlint_standard_function-signature = disabled 22 | ktlint_standard_function-expression-body = disabled 23 | ktlint_standard_function-literal = disabled 24 | ktlint_standard_class-signature = disabled 25 | ktlint_standard_block-comment-initial-star-alignment = disabled 26 | ktlint_standard_indent = disabled 27 | ktlint_standard_no-semi = disabled 28 | ktlint_standard_unnecessary-parentheses-before-trailing-lambda = disabled 29 | # Wrapping 30 | ktlint_standard_argument-list-wrapping = disabled 31 | ktlint_standard_parameter-list-wrapping = disabled 32 | ktlint_standard_binary-expression-wrapping = disabled 33 | ktlint_standard_property-wrapping = disabled 34 | ktlint_standard_parameter-wrapping = disabled 35 | ktlint_standard_enum-wrapping = disabled 36 | ktlint_standard_statement-wrapping = disabled 37 | ktlint_standard_condition-wrapping = disabled 38 | ktlint_standard_wrapping = disabled 39 | # Naming 40 | ktlint_standard_function-naming = disabled 41 | ktlint_standard_property-naming = disabled 42 | ktlint_standard_backing-property-naming = disabled 43 | # Spacing 44 | ktlint_standard_spacing-between-declarations-with-comments = disabled 45 | ktlint_standard_function-type-modifier-spacing = disabled 46 | [*.md] 47 | trim_trailing_whitespace = false 48 | [gradle/verification-metadata.xml] 49 | indent_size = 3 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | .cxx 10 | local.properties 11 | /.kotlin 12 | -------------------------------------------------------------------------------- /AndroidRealCA-Modules.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenisBronx/Real-Clean-Architecture-In-Android---Sample/5b69453ff688f34caf0b04c3ccde77c133cfdfae/AndroidRealCA-Modules.png -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.android.application) 3 | alias(libs.plugins.kotlin.android) 4 | alias(libs.plugins.compose.compiler) 5 | alias(libs.plugins.kotlin.serialization) 6 | } 7 | 8 | android { 9 | namespace = "com.denisbrandi.androidrealca" 10 | compileSdk = 35 11 | 12 | defaultConfig { 13 | applicationId = "com.denisbrandi.androidrealca" 14 | minSdk = 24 15 | targetSdk = 35 16 | versionCode = 1 17 | versionName = "1.0" 18 | 19 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 20 | vectorDrawables { 21 | useSupportLibrary = true 22 | } 23 | } 24 | 25 | buildTypes { 26 | release { 27 | isMinifyEnabled = false 28 | proguardFiles( 29 | getDefaultProguardFile("proguard-android-optimize.txt"), 30 | "proguard-rules.pro" 31 | ) 32 | } 33 | } 34 | compileOptions { 35 | sourceCompatibility = JavaVersion.VERSION_17 36 | targetCompatibility = JavaVersion.VERSION_17 37 | } 38 | kotlinOptions { 39 | jvmTarget = "17" 40 | } 41 | buildFeatures { 42 | compose = true 43 | } 44 | composeOptions { 45 | kotlinCompilerExtensionVersion = libs.versions.kotlin.compiler.extension.get() 46 | } 47 | packaging { 48 | resources { 49 | excludes += "/META-INF/{AL2.0,LGPL2.1}" 50 | } 51 | } 52 | } 53 | 54 | dependencies { 55 | implementation(project(":designsystem")) 56 | implementation(project(":cache")) 57 | implementation(project(":httpclient")) 58 | implementation(project(":user-component")) 59 | implementation(project(":product-component")) 60 | implementation(project(":wishlist-component")) 61 | implementation(project(":cart-component")) 62 | implementation(project(":onboarding-ui")) 63 | implementation(project(":plp-ui")) 64 | implementation(project(":wishlist-ui")) 65 | implementation(project(":cart-ui")) 66 | implementation(project(":main-ui")) 67 | 68 | implementation(libs.multiplatform.settings) 69 | implementation(libs.preferences.ktx) 70 | implementation(libs.androidx.core.ktx) 71 | implementation(libs.androidx.lifecycle.runtime.ktx) 72 | implementation(libs.androidx.activity.compose) 73 | implementation(platform(libs.androidx.compose.bom)) 74 | implementation(libs.compose.navigation) 75 | implementation(libs.androidx.ui) 76 | implementation(libs.androidx.ui.graphics) 77 | implementation(libs.androidx.ui.tooling.preview) 78 | implementation(libs.androidx.material3) 79 | testImplementation(libs.junit) 80 | debugImplementation(libs.androidx.ui.tooling) 81 | debugImplementation(libs.androidx.ui.test.manifest) 82 | } 83 | -------------------------------------------------------------------------------- /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 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/denisbrandi/androidrealca/App.kt: -------------------------------------------------------------------------------- 1 | package com.denisbrandi.androidrealca 2 | 3 | import android.app.Application 4 | import com.denisbrandi.androidrealca.di.Injector 5 | 6 | class App : Application() { 7 | override fun onCreate() { 8 | super.onCreate() 9 | Injector.start(this) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/denisbrandi/androidrealca/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.denisbrandi.androidrealca 2 | 3 | import android.os.Bundle 4 | import androidx.activity.* 5 | import androidx.activity.compose.setContent 6 | import com.denisbrandi.androidrealca.designsystem.RealCleanArchitectureInAndroidTheme 7 | import com.denisbrandi.androidrealca.navigation.RootNavigation 8 | 9 | class MainActivity : ComponentActivity() { 10 | override fun onCreate(savedInstanceState: Bundle?) { 11 | super.onCreate(savedInstanceState) 12 | enableEdgeToEdge() 13 | setContent { 14 | RealCleanArchitectureInAndroidTheme { 15 | RootNavigation() 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/denisbrandi/androidrealca/di/AndroidCacheProvider.kt: -------------------------------------------------------------------------------- 1 | package com.denisbrandi.androidrealca.di 2 | 3 | import android.content.Context 4 | import androidx.preference.PreferenceManager 5 | import com.denisbrandi.androidrealca.cache.* 6 | import com.russhwolf.settings.SharedPreferencesSettings 7 | import kotlinx.serialization.KSerializer 8 | 9 | class AndroidCacheProvider( 10 | private val applicationContext: Context 11 | ) : CacheProvider { 12 | 13 | private val settings by lazy { 14 | val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(applicationContext) 15 | SharedPreferencesSettings(sharedPrefs) 16 | } 17 | 18 | override fun getCachedObject( 19 | fileName: String, 20 | serializer: KSerializer, 21 | defaultValue: T 22 | ): CachedObject { 23 | return RealCachedObject(fileName, settings, serializer, defaultValue) 24 | } 25 | 26 | override fun getFlowCachedObject( 27 | fileName: String, 28 | serializer: KSerializer, 29 | defaultValue: T 30 | ): FlowCachedObject { 31 | return RealFlowCachedObject(getCachedObject(fileName, serializer, defaultValue)) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/denisbrandi/androidrealca/di/Injector.kt: -------------------------------------------------------------------------------- 1 | package com.denisbrandi.androidrealca.di 2 | 3 | import android.content.Context 4 | import com.denisbrandi.androidrealca.cart.di.* 5 | import com.denisbrandi.androidrealca.httpclient.RealHttpClientProvider 6 | import com.denisbrandi.androidrealca.main.di.MainUIDI 7 | import com.denisbrandi.androidrealca.onboarding.di.OnboardingUIDI 8 | import com.denisbrandi.androidrealca.plp.di.PLPUIDI 9 | import com.denisbrandi.androidrealca.product.di.ProductComponentDI 10 | import com.denisbrandi.androidrealca.user.di.UserComponentDI 11 | import com.denisbrandi.androidrealca.wishlist.di.* 12 | 13 | class Injector private constructor( 14 | applicationContext: Context 15 | ) { 16 | private val httpClient = RealHttpClientProvider.getClient() 17 | private val cacheProvider = AndroidCacheProvider(applicationContext) 18 | private val userComponentDI = UserComponentDI(httpClient, cacheProvider) 19 | private val productComponentDI = ProductComponentDI(httpClient) 20 | private val wishlistComponentDI = WishlistComponentDI(cacheProvider, userComponentDI.getUser) 21 | private val cartComponentDI = CartComponentDI(cacheProvider, userComponentDI.getUser) 22 | val isUserLoggedIn = userComponentDI.isUserLoggedIn 23 | val onboardingUIDI = OnboardingUIDI(userComponentDI.login) 24 | val plpUIDI = PLPUIDI( 25 | userComponentDI.getUser, 26 | productComponentDI.getProducts, 27 | wishlistComponentDI, 28 | cartComponentDI.addCartItem 29 | ) 30 | val wishlistUIDI = WishlistUIDI(wishlistComponentDI, cartComponentDI.addCartItem) 31 | val cartUIDI = CartUIDI(cartComponentDI) 32 | val mainUIDI = MainUIDI( 33 | wishlistComponentDI.observeUserWishlistIds, 34 | cartComponentDI.observeUserCart 35 | ) 36 | 37 | companion object { 38 | lateinit var INSTANCE: Injector 39 | 40 | fun start(applicationContext: Context) { 41 | INSTANCE = Injector(applicationContext) 42 | } 43 | } 44 | } 45 | 46 | val injector = Injector.INSTANCE 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/denisbrandi/androidrealca/navigation/RootNavigation.kt: -------------------------------------------------------------------------------- 1 | package com.denisbrandi.androidrealca.navigation 2 | 3 | import androidx.compose.runtime.Composable 4 | import androidx.navigation.compose.* 5 | import com.denisbrandi.androidrealca.di.injector 6 | import kotlinx.serialization.Serializable 7 | 8 | @Serializable 9 | object NavSplash 10 | 11 | @Serializable 12 | object NavLogin 13 | 14 | @Serializable 15 | object NavMain 16 | 17 | @Composable 18 | fun RootNavigation() { 19 | val navController = rememberNavController() 20 | NavHost(navController, startDestination = NavSplash) { 21 | composable { 22 | val destination: Any = if (injector.isUserLoggedIn()) { 23 | NavMain 24 | } else { 25 | NavLogin 26 | } 27 | navController.navigate(route = destination) 28 | } 29 | composable { 30 | injector.onboardingUIDI.LoginScreenDI { 31 | navController.navigate(route = NavMain) 32 | } 33 | } 34 | composable { 35 | injector.mainUIDI.MainScreenDI( 36 | makePLPScreen = { injector.plpUIDI.PLPScreenDI() }, 37 | makeWishlistScreen = { injector.wishlistUIDI.WishlistScreenDI() }, 38 | makeCartScreen = { injector.cartUIDI.CartScreenDI() } 39 | ) 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /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/DenisBronx/Real-Clean-Architecture-In-Android---Sample/5b69453ff688f34caf0b04c3ccde77c133cfdfae/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenisBronx/Real-Clean-Architecture-In-Android---Sample/5b69453ff688f34caf0b04c3ccde77c133cfdfae/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenisBronx/Real-Clean-Architecture-In-Android---Sample/5b69453ff688f34caf0b04c3ccde77c133cfdfae/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenisBronx/Real-Clean-Architecture-In-Android---Sample/5b69453ff688f34caf0b04c3ccde77c133cfdfae/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenisBronx/Real-Clean-Architecture-In-Android---Sample/5b69453ff688f34caf0b04c3ccde77c133cfdfae/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenisBronx/Real-Clean-Architecture-In-Android---Sample/5b69453ff688f34caf0b04c3ccde77c133cfdfae/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenisBronx/Real-Clean-Architecture-In-Android---Sample/5b69453ff688f34caf0b04c3ccde77c133cfdfae/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenisBronx/Real-Clean-Architecture-In-Android---Sample/5b69453ff688f34caf0b04c3ccde77c133cfdfae/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenisBronx/Real-Clean-Architecture-In-Android---Sample/5b69453ff688f34caf0b04c3ccde77c133cfdfae/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenisBronx/Real-Clean-Architecture-In-Android---Sample/5b69453ff688f34caf0b04c3ccde77c133cfdfae/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Real Clean Architecture in Android 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |