Skip to content

Commit

Permalink
2.6.0-alpha08 (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nek-12 committed Apr 17, 2024
2 parents 3e152df + 611d5bc commit cacd592
Show file tree
Hide file tree
Showing 53 changed files with 816 additions and 247 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,3 @@ hs_err_pid*
/.idea/deploymentTargetSelector.xml
**/plugin_encrypted_key.pem
**/plugin_rsa_private_key.pem
/certificates/keystore.jks
4 changes: 2 additions & 2 deletions buildSrc/src/main/kotlin/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ object Config {

const val artifactId = "$group.$artifact"

const val versionCode = 2
const val versionCode = 3
const val majorRelease = 2
const val minorRelease = 5
const val patch = 0
const val postfix = "-alpha07" // include dash (-)
const val postfix = "-alpha08" // include dash (-)
const val majorVersionName = "$majorRelease.$minorRelease.$patch"
const val versionName = "$majorVersionName$postfix"
const val url = "https://github.com/respawn-app/FlowMVI"
Expand Down
7 changes: 5 additions & 2 deletions buildSrc/src/main/kotlin/ConfigureMultiplatform.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
import org.gradle.api.Project
import org.gradle.kotlin.dsl.getValue
import org.gradle.kotlin.dsl.getting
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinHierarchyBuilder
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl

@OptIn(ExperimentalWasmDsl::class)
@OptIn(ExperimentalWasmDsl::class, ExperimentalKotlinGradlePluginApi::class)
fun Project.configureMultiplatform(
ext: KotlinMultiplatformExtension,
jvm: Boolean = true,
Expand All @@ -20,10 +22,11 @@ fun Project.configureMultiplatform(
windows: Boolean = true,
wasmJs: Boolean = true,
wasmWasi: Boolean = false, // TODO: Coroutines do not support wasmWasi yet
configure: KotlinHierarchyBuilder.Root.() -> Unit = {},
) = ext.apply {
val libs by versionCatalog
explicitApi()
applyDefaultHierarchyTemplate()
applyDefaultHierarchyTemplate(configure)
withSourcesJar(true)

if (linux) {
Expand Down
Binary file added certificates/keystore.jks
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ public inline fun <reified T> Any?.typed(): T? = this as? T
/**
* Get the name of the class, removing the "State" suffix, if present.
*/
@Deprecated("Usage of this function leads to some unintended consequences when enabling code obfuscation")
public inline fun <reified T : MVIState> nameByType(): String? = T::class.simpleName?.removeSuffix("State")
1 change: 0 additions & 1 deletion sample/androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ android {
buildFeatures {
buildConfig = true
compose = true
viewBinding = true
}
applicationVariants.all {
setProperty("archivesBaseName", Config.Sample.namespace)
Expand Down
2 changes: 1 addition & 1 deletion sample/androidApp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
</activity>

<activity
android:name=".XmlActivity"
android:name="pro.respawn.flowmvi.sample.ui.screens.XmlActivity"
android:exported="false">
</activity>
</application>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import org.koin.android.scope.AndroidScopeComponent
import org.koin.androidx.compose.KoinAndroidContext
import org.koin.androidx.scope.activityRetainedScope
import org.koin.core.annotation.KoinExperimentalAPI
import pro.respawn.flowmvi.sample.navigation.AndroidFeatureLauncher
import pro.respawn.flowmvi.sample.navigation.AppContent
import pro.respawn.flowmvi.sample.navigation.component.RootComponent
import pro.respawn.kmmutils.common.fastLazy
Expand Down

This file was deleted.

4 changes: 4 additions & 0 deletions sample/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ kotlin {
implementation(compose.desktop.currentOs)
}
androidMain.dependencies {
implementation(projects.android)
implementation(applibs.view.constraintlayout)
implementation(applibs.view.material)
implementation(applibs.koin.android)
}
wasmJsMain.dependencies {
Expand All @@ -108,6 +111,7 @@ android {
namespace = Config.Sample.namespace
configureAndroidLibrary(this)
buildFeatures {
viewBinding = true
buildConfig = true
compose = true
}
Expand Down
2 changes: 2 additions & 0 deletions sample/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ material = "1.12.0-rc01"
activity = "1.9.0-rc01"
okio = "3.9.0"
splashscreen = "1.1.0-rc01"
xml-constraintlayout = "2.2.0-alpha13"
#codehighlights = "0.8.0"

[libraries]
Expand All @@ -29,6 +30,7 @@ compose-activity = { module = "androidx.activity:activity-compose", version.ref
androidx-activity = { module = "androidx.activity:activity-ktx", version.ref = "activity" }
androidx-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "splashscreen" }
view-material = { module = "com.google.android.material:material", version.ref = "material" }
view-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "xml-constraintlayout" }

#compose-codehighlighting = { module = "dev.snipme:highlights", version.ref = "codehighlights" }

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
package pro.respawn.flowmvi.sample.di

import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.core.module.dsl.factoryOf
import org.koin.core.module.dsl.singleOf
import org.koin.core.qualifier.qualifier
import org.koin.dsl.bind
import org.koin.dsl.module
import pro.respawn.flowmvi.android.StoreViewModel
import pro.respawn.flowmvi.sample.features.xmlactivity.XmlActivityContainer
import pro.respawn.flowmvi.sample.platform.AndroidFileManager
import pro.respawn.flowmvi.sample.platform.FileManager

actual val platformAppModule = module {
singleOf(::AndroidFileManager) bind FileManager::class
factoryOf(::XmlActivityContainer)
viewModel(qualifier<XmlActivityContainer>()) { StoreViewModel(get<XmlActivityContainer>()) }
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package pro.respawn.flowmvi.sample.app
package pro.respawn.flowmvi.sample.navigation

import android.content.Context
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import pro.respawn.flowmvi.sample.platform.PlatformFeatureLauncher
import pro.respawn.flowmvi.sample.ui.screens.XmlActivity

internal class AndroidFeatureLauncher(private val context: Context) : PlatformFeatureLauncher {
class AndroidFeatureLauncher(private val context: Context) : PlatformFeatureLauncher {

override fun xmlActivity() = context.startActivity(
Intent(context, XmlActivity::class.java).apply {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ class AndroidFileManager(context: Context) : FileManager {

private val cacheDir = context.cacheDir

override fun cacheDir(relative: String): String = cacheDir.resolve(relative).absolutePath
override fun cacheFile(dir: String, filename: String): String = cacheDir.resolve(dir).resolve(filename).absolutePath
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package pro.respawn.flowmvi.sample.ui.screens

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.core.view.isVisible
import com.google.android.material.snackbar.Snackbar
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.qualifier.qualifier
import pro.respawn.flowmvi.android.StoreViewModel
import pro.respawn.flowmvi.android.subscribe
import pro.respawn.flowmvi.sample.R
import pro.respawn.flowmvi.sample.databinding.ActivityXmlBinding
import pro.respawn.flowmvi.sample.features.xmlactivity.XmlActivityAction
import pro.respawn.flowmvi.sample.features.xmlactivity.XmlActivityAction.ShowIncrementedSnackbar
import pro.respawn.flowmvi.sample.features.xmlactivity.XmlActivityContainer
import pro.respawn.flowmvi.sample.features.xmlactivity.XmlActivityIntent
import pro.respawn.flowmvi.sample.features.xmlactivity.XmlActivityIntent.ClickedIncrementCounter
import pro.respawn.flowmvi.sample.features.xmlactivity.XmlActivityState
import pro.respawn.flowmvi.sample.features.xmlactivity.XmlActivityState.DisplayingCounter
import pro.respawn.kmmutils.common.fastLazy

private typealias ViewModel = StoreViewModel<XmlActivityState, XmlActivityIntent, XmlActivityAction>

internal class XmlActivity : ComponentActivity() {

private val vm by viewModel<ViewModel>(qualifier<XmlActivityContainer>())
private val binding by fastLazy { ActivityXmlBinding.inflate(layoutInflater) }

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
subscribe(vm.store, ::consume, ::render)
with(binding) {
btnIncrement.setOnClickListener { vm.store.intent(ClickedIncrementCounter) }
}
}

private fun render(state: XmlActivityState) = with(binding) {
when (state) {
is DisplayingCounter -> {
tvCounter.isVisible = true
btnIncrement.isVisible = true
tvCounter.text = getString(R.string.counter_template, state.counter)

tvError.isVisible = false
progress.isVisible = false
}
is XmlActivityState.Error -> {
tvError.isVisible = true
tvError.text = state.e?.message ?: getString(R.string.error_message)

progress.isVisible = false
tvCounter.isVisible = false
btnIncrement.isVisible = false
}
is XmlActivityState.Loading -> {
progress.isVisible = true

tvError.isVisible = false
tvCounter.isVisible = false
btnIncrement.isVisible = false
}
}
}

private fun consume(action: XmlActivityAction) {
when (action) {
ShowIncrementedSnackbar -> Snackbar.make(
binding.root,
getString(R.string.incremented_counter_message),
Snackbar.LENGTH_SHORT
).show()
}
}
}
68 changes: 68 additions & 0 deletions sample/src/androidMain/res/layout/activity_xml.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.screens.XmlActivity">


<com.google.android.material.textview.MaterialTextView
android:id="@+id/tvCounter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:gravity="center"
android:textSize="16sp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/btnIncrement"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.5"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Counter: 5"
tools:visibility="visible" />

<com.google.android.material.button.MaterialButton
android:id="@+id/btnIncrement"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="8dp"
android:text="@string/increment_counter"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.502"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvCounter"
app:layout_constraintVertical_bias="0.5"
tools:visibility="visible" />

<com.google.android.material.textview.MaterialTextView
android:id="@+id/tvError"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:textColor="@color/design_default_color_error"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Error"
tools:visibility="visible" />

<com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
14 changes: 14 additions & 0 deletions sample/src/androidMain/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="increment_counter">Increment counter</string>
<string name="incremented_counter_message">Incremented counter</string>
<string name="counter_template">
This feature showcases how you can implement multiplatform business logic and hook it up to a native UI.
In this case, this activity is implemented using XML, but the store is in the shared module.
\n\nFlowMVI provides a way to wrap your stores in ViewModels and automatically start/stop them as needed, then inject them
into your UI components.
\n\nAs needed, you can even persist the state of a store into a platform-dependent container, i.e. SavedInstanceState
\nCounter : %d
</string>
<string name="error_message">Unknown error</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,21 @@ import pro.respawn.flowmvi.savedstate.api.NullRecover
import pro.respawn.flowmvi.savedstate.api.Saver
import pro.respawn.flowmvi.savedstate.dsl.CompressedFileSaver
import pro.respawn.flowmvi.savedstate.dsl.JsonSaver
import pro.respawn.flowmvi.savedstate.dsl.NoOpSaver
import pro.respawn.flowmvi.savedstate.dsl.LoggingSaver
import pro.respawn.flowmvi.savedstate.plugins.saveStatePlugin

internal class DefaultStoreConfiguration(
files: FileManager,
private val files: FileManager,
private val json: Json,
) : StoreConfiguration {

private val cacheDir = files.cacheDir(StoreCacheDirName)

override fun <S : MVIState> saver(
serializer: KSerializer<S>,
fileName: String,
): Saver<S> {
return CompressedFileSaver(
dir = cacheDir ?: return NoOpSaver(),
fileName = "$fileName.gz",
recover = NullRecover
).let { JsonSaver(json, serializer, it) }
}
) = CompressedFileSaver(
path = files.cacheFile("states", "$fileName.json"),
recover = NullRecover
).let { JsonSaver(json, serializer, it) }

override operator fun <S : MVIState, I : MVIIntent, A : MVIAction> StoreBuilder<S, I, A>.invoke(
name: String,
Expand All @@ -53,7 +48,7 @@ internal class DefaultStoreConfiguration(
}
if (saver != null) install(
saveStatePlugin(
saver = saver,
saver = LoggingSaver(saver, tag = name, logger = logger),
name = "${name}SavedStatePlugin",
context = Dispatchers.Default,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
Expand Down Expand Up @@ -135,7 +136,7 @@ private fun DecomposeScreenContent(
}
is DisplayingPages -> Column(
modifier = Modifier
.fillMaxSize()
.fillMaxHeight()
.adaptiveWidth()
.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally
Expand Down
Loading

0 comments on commit cacd592

Please sign in to comment.