From caa0276b405c4e74187ff6fd36c43b6331823bfd Mon Sep 17 00:00:00 2001 From: galex Date: Wed, 22 May 2024 08:33:03 +0300 Subject: [PATCH] More progress towards diagnostic tests --- README.md | 72 +++++++++++++++++-- .../runners/DiagnosticTestGenerated.java | 2 + .../kotlin/dev/galex/yamvil/GenerateTests.kt | 2 +- .../yamvil/runners/AbstractDiagnosticTest.kt | 2 +- .../galex/yamvil/runners/BaseTestRunner.kt | 2 +- gradle/libs.versions.toml | 6 +- samples/sample-android/app/build.gradle.kts | 9 +++ .../sample-android/gradle/libs.versions.toml | 14 ++-- 8 files changed, 91 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index f59de01..d7c327d 100644 --- a/README.md +++ b/README.md @@ -5,17 +5,79 @@ [![codecov](https://codecov.io/github/galex/yamvil/branch/main/graph/badge.svg?token=ML8EN8PYP0)](https://codecov.io/github/galex/yamvil) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) -> Do we really need Yet Another MVI Library? Yes, we do! +> ⚠️ **This is a work in progress**: Yamvil is still in early development and is not ready for production use. The API is subject to change and Android Studio is not ready to run the compiler plugin, **yet**. Yamvil is a library and a compiler plugin to help write MVI Screens ensuring a proper Unidirectional Data Flow way for Android and Compose Multiplatform. -> ⚠️ **This is a work in progress**: Yamvil is still in early development and is not ready for production use. The API is subject to change and Android Studio is not ready to run the compiler plugin, **yet**. - ## Documentation -The full documentation of Yamvil [is available right here](https://docs.galex.dev/yamvil/). +The full documentation of Yamvil [is available here](https://docs.galex.dev/yamvil/). + +## To the Point + +Write MVI ViewModels like this: +```kotlin +class DashboardViewModel: MVIViewModel() { + + override fun initializeUiState(): DashboardUiState { + return DashboardUiState(state = DashboardUiState.ContentState.Loading) + } + override fun handleEvent(event: DashboardUiEvent) { + when (event) { + is DashboardUiEvent.ClickOnNext -> onClickOnNext() + } + } + + private fun onClickOnNext() { + update { copy(action = Consumable(DashboardUiAction.NavigateToNext)) } + } +} +``` +Then use your MVI ViewModel in a Composable like this: +```kotlin +@Composable +fun DashboardScreen( + uiState: DashboardUiState, + handleEvent: (DashboardUiEvent) -> Unit, + modifier: Modifier = Modifier +) { + when (uiState.state) { + is DashboardUiState.ContentState.Loading -> DashboardLoadingContent() + is DashboardUiState.ContentState.Error -> DashboardErrorContent() + is DashboardUiState.ContentState.Content -> DashboardContent(uiState.state) + } + + LaunchedActionEffect(uiState) { action: DashboardUiAction -> + when (action) { + DashboardUiAction.NavigateToNext -> {} + } + } +} +// (...) +``` +Or if you're using Fragments, like this: +```kotlin +class DashboardFragment: MVIFragment() { + + override val viewModel: DashboardViewModel by viewModels() + override fun observeUiState(uiState: DashboardUiState) { + when (uiState.state) { + DashboardUiState.ContentState.Loading -> onLoading() + is DashboardUiState.ContentState.Content -> onContent(uiState.state) + DashboardUiState.ContentState.Error -> onError() + } + + uiState.onAction { action -> + when (action) { + DashboardUiAction.NavigateToNext -> navigateToNext() + } + } + } + // (...) +} +``` -## Quick Start +## Installation In your libs.version.toml, add the following: diff --git a/compiler-plugin/src/test-gen/dev/conguard/compiler/runners/DiagnosticTestGenerated.java b/compiler-plugin/src/test-gen/dev/conguard/compiler/runners/DiagnosticTestGenerated.java index 217ce3d..6b8dbbe 100644 --- a/compiler-plugin/src/test-gen/dev/conguard/compiler/runners/DiagnosticTestGenerated.java +++ b/compiler-plugin/src/test-gen/dev/conguard/compiler/runners/DiagnosticTestGenerated.java @@ -11,6 +11,8 @@ import java.io.File; import java.util.regex.Pattern; +import dev.galex.yamvil.runners.AbstractDiagnosticTest; + /** This class is generated by {@link dev.galex.yamvil.GenerateTestsKt}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") @TestMetadata("src/test-data/diagnostics") diff --git a/compiler-plugin/src/test/kotlin/dev/galex/yamvil/GenerateTests.kt b/compiler-plugin/src/test/kotlin/dev/galex/yamvil/GenerateTests.kt index df21f72..340e891 100644 --- a/compiler-plugin/src/test/kotlin/dev/galex/yamvil/GenerateTests.kt +++ b/compiler-plugin/src/test/kotlin/dev/galex/yamvil/GenerateTests.kt @@ -1,6 +1,6 @@ package dev.galex.yamvil -import dev.conguard.compiler.runners.AbstractDiagnosticTest +import dev.galex.yamvil.runners.AbstractDiagnosticTest import org.jetbrains.kotlin.generators.generateTestGroupSuiteWithJUnit5 fun main() { diff --git a/compiler-plugin/src/test/kotlin/dev/galex/yamvil/runners/AbstractDiagnosticTest.kt b/compiler-plugin/src/test/kotlin/dev/galex/yamvil/runners/AbstractDiagnosticTest.kt index 39c4449..bd422cd 100644 --- a/compiler-plugin/src/test/kotlin/dev/galex/yamvil/runners/AbstractDiagnosticTest.kt +++ b/compiler-plugin/src/test/kotlin/dev/galex/yamvil/runners/AbstractDiagnosticTest.kt @@ -1,4 +1,4 @@ -package dev.conguard.compiler.runners +package dev.galex.yamvil.runners import org.jetbrains.kotlin.test.FirParser import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder diff --git a/compiler-plugin/src/test/kotlin/dev/galex/yamvil/runners/BaseTestRunner.kt b/compiler-plugin/src/test/kotlin/dev/galex/yamvil/runners/BaseTestRunner.kt index 90197c7..9441c33 100644 --- a/compiler-plugin/src/test/kotlin/dev/galex/yamvil/runners/BaseTestRunner.kt +++ b/compiler-plugin/src/test/kotlin/dev/galex/yamvil/runners/BaseTestRunner.kt @@ -1,4 +1,4 @@ -package dev.conguard.compiler.runners +package dev.galex.yamvil.runners import dev.conguard.compiler.services.ExtensionRegistrarConfigurator import dev.conguard.compiler.services.PluginDslProvider diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e4209ab..4b72c16 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,8 +1,8 @@ [versions] -agp = "8.3.0" +agp = "8.3.2" junitJupiterApi = "5.10.1" junitJupiterEngine = "5.10.1" -kotlin = "2.0.0-RC3" +kotlin = "2.0.0" compose = "1.6.7" compose-material3 = "1.2.1" androidx-activityCompose = "1.9.0" @@ -11,7 +11,7 @@ lifecycle-viewmodel-compose = "2.8.0-beta02" junit = "4.13.2" junit-bom = "5.10.1" autoservice = "1.0.1" -kotlin-compile-testing = "1.4.9" +kotlin-compile-testing = "1.5.0" gson = "2.10.1" robolectric = "4.12" truth = "1.4.2" diff --git a/samples/sample-android/app/build.gradle.kts b/samples/sample-android/app/build.gradle.kts index 731ef8c..862b2cc 100644 --- a/samples/sample-android/app/build.gradle.kts +++ b/samples/sample-android/app/build.gradle.kts @@ -1,3 +1,5 @@ +import dev.galex.yamvil.dsl.YamvilLevel + plugins { alias(libs.plugins.android.application) alias(libs.plugins.jetbrains.kotlin.android) @@ -75,4 +77,11 @@ dependencies { androidTestImplementation(libs.androidx.ui.test.junit4) debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.test.manifest) +} + +yamvil { + level = YamvilLevel.Warning + screenSuffix = "MVIScreen" // Default value is "Screen" + uiStateParameterName = "state" // Default value is "uiState" + uiEventFunctionParameterMame = "onEvent" // Default value is "handleEvent" } \ No newline at end of file diff --git a/samples/sample-android/gradle/libs.versions.toml b/samples/sample-android/gradle/libs.versions.toml index 8878d24..7c94e9e 100644 --- a/samples/sample-android/gradle/libs.versions.toml +++ b/samples/sample-android/gradle/libs.versions.toml @@ -1,15 +1,15 @@ [versions] -agp = "8.4.0" -kotlin = "2.0.0-RC3" -coreKtx = "1.10.1" +agp = "8.4.1" +kotlin = "2.0.0" +coreKtx = "1.13.1" junit = "4.13.2" junitVersion = "1.1.5" espressoCore = "3.5.1" -lifecycleRuntimeKtx = "2.6.1" +lifecycleRuntimeKtx = "2.8.0" activityCompose = "1.9.0" -composeBom = "2023.08.00" -yamvil = "0.0.1" -lifecycleViewmodelCompose = "2.7.0" +composeBom = "2024.05.00" +yamvil = "0.0.2" +lifecycleViewmodelCompose = "2.8.0" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }