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

#168 Jetpack Compose and SwiftUI integration with sample #175

Merged
merged 34 commits into from
Apr 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
1c2157d
#168 jetpack compose sample implemented
Alex009 Feb 25, 2022
5c1e0d1
#168 swiftui experiments
Alex009 Feb 25, 2022
021670f
swiftui navigation tests
Alex009 Mar 11, 2022
ea7b41b
more tests with swiftui updates
Alex009 Mar 11, 2022
91bb2c2
resultBuilder usage
Alex009 Mar 11, 2022
1f75827
works version with ObservableObject ViewModel
Alex009 Mar 11, 2022
fee3b82
#168 cleanup swiftui bindings code
Alex009 Mar 11, 2022
a2cbed2
#168 more support swiftui functions
Alex009 Mar 11, 2022
6cf9022
#168 separate views to files
Alex009 Mar 18, 2022
b91c020
#168 swiftify
Alex009 Mar 18, 2022
2b3ae4b
#168 ios navigation with events listener
Alex009 Mar 18, 2022
3d5306d
#168 new viewModel binding functions
Alex009 Mar 18, 2022
0773366
#168 swiftui variants and more screens
Alex009 Mar 18, 2022
db39529
#168 cflow implementation with swiftui bindings
Alex009 Mar 18, 2022
be0166e
#168 kswift enum usage
Alex009 Mar 18, 2022
cd2ca0f
#168 clean code
Alex009 Mar 18, 2022
07181e3
#168 migrate swiftui api to KeyPath getters
Alex009 Mar 18, 2022
e66ccd2
#168 open details screen swiftui
Alex009 Mar 18, 2022
89d7fdd
#168 cleanup swiftui code
Alex009 Mar 18, 2022
6a1d9da
#168 jetpack compose ui implemented for sample with navigation
Alex009 Mar 25, 2022
b9abccb
Merge branch 'develop' into declarative-ui
Alex009 Apr 15, 2022
2a7fa7f
#168 new mvvm-flow module
Alex009 Apr 15, 2022
92a2a0b
#168 simplify login binding on swiftui
Alex009 Apr 15, 2022
457f82e
#168 compose additional modules
Alex009 Apr 16, 2022
80af59b
#168 use swift additions as precombiled xcframework
Alex009 Apr 29, 2022
29b3695
#168 new bindings
Alex009 Apr 29, 2022
8488836
#168 setup publication of swiftui additions to maven with pods
Alex009 Apr 29, 2022
d69f56a
#168 fix compilation of flow tests
Alex009 Apr 29, 2022
9c454ea
#168 disable publishing of utility project
Alex009 Apr 30, 2022
bd539cf
#168 change podspec url to mavenCentral
Alex009 Apr 30, 2022
b12ec99
#168 rename declarative ui sample dir
Alex009 Apr 30, 2022
bef05a9
#168 disable tests of flow binding for ios (can't fix it)
Alex009 Apr 30, 2022
d0df558
up version in readme
Alex009 Apr 30, 2022
4be0c56
#168 fix linux compilation
Alex009 Apr 30, 2022
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
39 changes: 24 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,18 @@ allprojects {
project build.gradle
```groovy
dependencies {
commonMainApi("dev.icerock.moko:mvvm-core:0.12.0") // only ViewModel, EventsDispatcher, Dispatchers.UI
commonMainApi("dev.icerock.moko:mvvm-livedata:0.12.0") // api mvvm-core, LiveData and extensions
commonMainApi("dev.icerock.moko:mvvm-state:0.12.0") // api mvvm-livedata, ResourceState class and extensions
commonMainApi("dev.icerock.moko:mvvm-livedata-resources:0.12.0") // api mvvm-core, moko-resources, extensions for LiveData with moko-resources
commonMainApi("dev.icerock.moko:mvvm-core:0.13.0") // only ViewModel, EventsDispatcher, Dispatchers.UI
commonMainApi("dev.icerock.moko:mvvm-livedata:0.13.0") // api mvvm-core, LiveData and extensions
commonMainApi("dev.icerock.moko:mvvm-state:0.13.0") // api mvvm-livedata, ResourceState class and extensions
commonMainApi("dev.icerock.moko:mvvm-livedata-resources:0.13.0") // api mvvm-core, moko-resources, extensions for LiveData with moko-resources

androidMainApi("dev.icerock.moko:mvvm-livedata-material:0.12.0") // api mvvm-livedata, Material library android extensions
androidMainApi("dev.icerock.moko:mvvm-livedata-glide:0.12.0") // api mvvm-livedata, Glide library android extensions
androidMainApi("dev.icerock.moko:mvvm-livedata-swiperefresh:0.12.0") // api mvvm-livedata, SwipeRefreshLayout library android extensions
androidMainApi("dev.icerock.moko:mvvm-databinding:0.12.0") // api mvvm-livedata, DataBinding support for Android
androidMainApi("dev.icerock.moko:mvvm-viewbinding:0.12.0") // api mvvm-livedata, ViewBinding support for Android
androidMainApi("dev.icerock.moko:mvvm-livedata-material:0.13.0") // api mvvm-livedata, Material library android extensions
androidMainApi("dev.icerock.moko:mvvm-livedata-glide:0.13.0") // api mvvm-livedata, Glide library android extensions
androidMainApi("dev.icerock.moko:mvvm-livedata-swiperefresh:0.13.0") // api mvvm-livedata, SwipeRefreshLayout library android extensions
androidMainApi("dev.icerock.moko:mvvm-databinding:0.13.0") // api mvvm-livedata, DataBinding support for Android
androidMainApi("dev.icerock.moko:mvvm-viewbinding:0.13.0") // api mvvm-livedata, ViewBinding support for Android

commonTestImplementation("dev.icerock.moko:mvvm-test:0.12.0") // test utilities
commonTestImplementation("dev.icerock.moko:mvvm-test:0.13.0") // test utilities
}
```

Expand All @@ -61,10 +61,10 @@ kotlin {
// export correct artifact to use all classes of library directly from Swift
targets.withType(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget::class.java).all {
binaries.withType(org.jetbrains.kotlin.gradle.plugin.mpp.Framework::class.java).all {
export("dev.icerock.moko:mvvm-core:0.12.0")
export("dev.icerock.moko:mvvm-livedata:0.12.0")
export("dev.icerock.moko:mvvm-livedata-resources:0.12.0")
export("dev.icerock.moko:mvvm-state:0.12.0")
export("dev.icerock.moko:mvvm-core:0.13.0")
export("dev.icerock.moko:mvvm-livedata:0.13.0")
export("dev.icerock.moko:mvvm-livedata-resources:0.13.0")
export("dev.icerock.moko:mvvm-state:0.13.0")
}
}
}
Expand All @@ -75,6 +75,14 @@ kotlin {
For iOS we recommend use [moko-kswift](https://github.com/icerockdev/moko-kswift) with extensions
generation enabled. All `LiveData` to `UIView` bindings is extensions for UI elements.

### SwiftUI additions

To use MOKO MVVM with SwiftUI set name of your kotlin framework to `MultiPlatformLibrary` and add
dependency to CocoaPods:
```ruby
pod 'mokoMvvmFlowSwiftUI', :podspec => 'https://raw.githubusercontent.com/icerockdev/moko-mvvm/release/0.13.0/mokoMvvmFlowSwiftUI.podspec'
```

## Documentation
Documentation generated by Dokka and available at https://icerockdev.github.io/moko-mvvm/

Expand Down Expand Up @@ -498,7 +506,8 @@ Please see more examples in the [sample directory](sample).
- The [mvvm-databinding directory](mvvm-databinding) contains DataBinding support code for Android;
- The [mvvm-viewbinding directory](mvvm-viewbinding) contains ViewBinding support code for Android;
- The [mvvm-test directory](mvvm-test) contains the test utilities;
- In [sample directory](sample) contains sample apps for Android and iOS; plus the mpp-library connected to the apps.
- In [sample directory](sample) contains sample apps for Android and iOS; plus the mpp-library connected to the apps;
- In [sample-declarative-ui directory](sample-declarative-ui) contains sample apps with Jetpack Compose and SwiftUI.

## Contributing
All development (both new features and bug fixes) is performed in the `develop` branch. This way `master` always contains the sources of the most recently released version. Please send PRs with bug fixes to the `develop` branch. Documentation fixes in the markdown files are an exception to this rule. They are updated directly in `master`.
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ buildscript {
dependencies {
classpath(":mvvm-build-logic")
classpath(libs.kswiftGradlePlugin)
classpath(libs.composeJetBrainsGradlePlugin)
}
}

Expand Down
10 changes: 9 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,26 @@ androidLifecycleVersion = "2.2.0"
coroutinesVersion = "1.6.0-native-mt"
mokoResourcesVersion = "0.18.0"
mokoTestVersion = "0.6.1"
mokoMvvmVersion = "0.12.0"
mokoMvvmVersion = "0.13.0"
mokoKSwiftVersion = "0.4.0"
composeVersion = "1.1.1"
composeJetBrainsVersion = "1.1.1"

[libraries]
# android
appCompat = { module = "androidx.appcompat:appcompat", version = "1.2.0" }
material = { module = "com.google.android.material:material", version = "1.2.1" }
lifecycle = { module = "androidx.lifecycle:lifecycle-extensions", version.ref = "androidLifecycleVersion" }
lifecycleKtx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidLifecycleVersion" }
androidViewModel = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidLifecycleVersion" }
androidLiveData = { module = "androidx.lifecycle:lifecycle-livedata-ktx", version.ref = "androidLifecycleVersion" }
glide = { module = "com.github.bumptech.glide:glide", version = "4.11.0" }
swipeRefresh = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version = "1.1.0" }

# compose
composeFoundation = { module = "androidx.compose.foundation:foundation", version.ref = "composeVersion" }
composeLiveData = { module = "androidx.compose.runtime:runtime-livedata", version.ref = "composeVersion" }

# coroutines
coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutinesVersion" }
coroutinesTest = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutinesVersion" }
Expand All @@ -37,6 +44,7 @@ mobileMultiplatformGradlePlugin = { module = "dev.icerock:mobile-multiplatform",
androidGradlePlugin = { module = "com.android.tools.build:gradle", version = "7.0.4" }
detektGradlePlugin = { module = "io.gitlab.arturbosch.detekt:detekt-gradle-plugin", version = "1.19.0" }
kswiftGradlePlugin = { module = "dev.icerock.moko:kswift-gradle-plugin", version.ref = "mokoKSwiftVersion" }
composeJetBrainsGradlePlugin = { module = "org.jetbrains.compose:compose-gradle-plugin", version.ref = "composeJetBrainsVersion" }

[plugins]
nexusPublish = { id = "io.github.gradle-nexus.publish-plugin", version = "1.1.0" }
19 changes: 19 additions & 0 deletions mokoMvvmFlowSwiftUI.podspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Pod::Spec.new do |s|
s.name = 'mokoMvvmFlowSwiftUI'
s.version = '0.13.0'
s.summary = 'MOKO MVVM SwiftUI additions for Flow'
s.description = 'some description here'
s.homepage = 'localhost'
s.license = { :type => 'Apache 2' }
s.authors = 'IceRock Development'
s.source = {
:http => "https://repo1.maven.org/maven2/dev/icerock/moko/mvvm-flow-swiftui/#{s.version}/mvvm-flow-swiftui-#{s.version}.zip",
:type => "zip"
}

s.platform = :ios
s.ios.deployment_target = '13.0'
s.ios.vendored_framework = 'mokoMvvmFlowSwiftUI.xcframework'

s.requires_arc = true
end
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ inline fun <reified T : ViewModel> ViewModelStoreOwner.getViewModel(
ViewModelFactory { viewModelBlock() }
).get(T::class.java)

inline fun <reified T : ViewModel> ViewModelStoreOwner.createViewModelFactory(
inline fun <reified T : ViewModel> createViewModelFactory(
noinline viewModelBlock: () -> T
): ViewModelFactory = ViewModelFactory {
viewModelBlock()
Expand Down
34 changes: 34 additions & 0 deletions mvvm-flow-compose/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2022 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
*/

plugins {
id("org.jetbrains.kotlin.multiplatform")
id("detekt-convention")
id("org.jetbrains.compose")
id("javadoc-stub-convention")
id("publication-convention")
}

java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(11))
}
}

kotlin {
jvm()
js(IR) {
browser()
}

sourceSets {
commonMain {
dependencies {
api(projects.mvvmFlow)

api(compose.runtime)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright 2022 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
*/

package dev.icerock.moko.mvvm.flow.compose

import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.onEach

@Composable
fun <T> Flow<T>.observeAsActions(onEach: (T) -> Unit) {
val flow = this
LaunchedEffect(key1 = flow) {
flow.onEach(onEach).collect()
}
}
98 changes: 98 additions & 0 deletions mvvm-flow/apple/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework
import org.jetbrains.kotlin.konan.target.HostManager

plugins {
id("detekt-convention")
id("org.jetbrains.kotlin.multiplatform")
id("dev.icerock.mobile.multiplatform.apple-framework")
id("publication-convention")
}

kotlin {
iosArm64()
iosX64()
iosSimulatorArm64()
macosX64()

val xcf = XCFramework("MultiPlatformLibrary")
targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>()
.configureEach {
binaries.withType<org.jetbrains.kotlin.gradle.plugin.mpp.Framework>().configureEach {
xcf.add(this)
}
}
}

dependencies {
commonMainImplementation(libs.coroutines)

commonMainApi(libs.mokoResources)
commonMainApi(projects.mvvmFlow)
commonMainApi(projects.mvvmCore)
}

framework {
export(projects.mvvmCore)
export(projects.mvvmFlow)
export(libs.mokoResources)
}

val swiftXCFrameworkProject = File(projectDir, "xcode/mokoMvvmFlow.xcodeproj")
val swiftXCFrameworkOutput = File(projectDir, "xcode/xcframework")
val swiftXCFramework = File(swiftXCFrameworkOutput, "mokoMvvmFlowSwiftUI.xcframework")
val swiftXCFrameworkArchive = File(swiftXCFrameworkOutput, "mokoMvvmFlowSwiftUI.xcframework.zip")

val compileTask = tasks.create("compileMokoFlowSwiftUIXCFramework", Exec::class) {
group = "xcode"

commandLine = listOf(
"xcodebuild",
"-scheme",
"mokoMvvmFlowSwiftUI",
"-project",
swiftXCFrameworkProject.absolutePath,
"build"
)

dependsOn("assembleMultiPlatformLibraryDebugXCFramework")

onlyIf { HostManager.hostIsMac }
}

val archiveTask = tasks.create("archiveMokoFlowSwiftUIXCFramework", Zip::class) {
group = "xcode"

from(swiftXCFramework)
into(swiftXCFramework.name)

archiveFileName.set(swiftXCFrameworkArchive.name)
destinationDirectory.set(swiftXCFrameworkOutput)

dependsOn(compileTask)

onlyIf { HostManager.hostIsMac }
}

val publicationName = "swiftuiAdditions"

publishing {
publications {
create<MavenPublication>(publicationName) {
artifactId = "mvvm-flow-swiftui"

artifact(archiveTask.archiveFile) {
extension = "zip"
}

pom {
packaging = "zip"
}
}
}
}

tasks.withType<AbstractPublishToMaven>()
.configureEach {
if (publication.name != publicationName) enabled = false
else onlyIf { HostManager.hostIsMac }
}
8 changes: 8 additions & 0 deletions mvvm-flow/apple/src/commonMain/kotlin/Greeting.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright 2022 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
*/

package dev.icerock.moko.mvvm.flow.apple

// just for compile this module
fun helloWorld() = println("hello world")
1 change: 1 addition & 0 deletions mvvm-flow/apple/xcode/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
xcframework/
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading