Skip to content

Commit 8f607d3

Browse files
authored
Merge pull request #200 from kovalandrew/#195-add-flow-resources
#184 #195 Add flow-resources with StringDesc bindings for Flow
2 parents ef2da69 + c8d5e65 commit 8f607d3

File tree

13 files changed

+347
-0
lines changed

13 files changed

+347
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ dependencies {
5555
commonMainApi("dev.icerock.moko:mvvm-livedata:0.13.1") // api mvvm-core, LiveData and extensions
5656
commonMainApi("dev.icerock.moko:mvvm-state:0.13.1") // api mvvm-livedata, ResourceState class and extensions
5757
commonMainApi("dev.icerock.moko:mvvm-livedata-resources:0.13.1") // api mvvm-core, moko-resources, extensions for LiveData with moko-resources
58+
commonMainApi("dev.icerock.moko:mvvm-flow-resources:0.13.1") // api mvvm-core, moko-resources, extensions for Flow with moko-resources
5859
5960
androidMainApi("dev.icerock.moko:mvvm-flow-compose:0.13.1") // api mvvm-flow, binding extensions for Jetpack Compose (jvm, js, android)
6061
androidMainApi("dev.icerock.moko:mvvm-livedata-compose:0.13.1") // api mvvm-livedata, binding extensions for Jetpack Compose (jvm, js, android)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* Copyright 2022 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
plugins {
6+
id("kmm-library-convention")
7+
id("detekt-convention")
8+
id("publication-convention")
9+
}
10+
11+
dependencies {
12+
commonMainApi(projects.mvvmFlow)
13+
commonMainApi(libs.mokoResources)
14+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest package="dev.icerock.moko.mvvm.flow.resources" />
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright 2022 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package dev.icerock.moko.mvvm.flow.resources
6+
7+
import android.widget.TextView
8+
import androidx.lifecycle.LifecycleOwner
9+
import dev.icerock.moko.mvvm.flow.CStateFlow
10+
import dev.icerock.moko.mvvm.flow.binding.bind
11+
import dev.icerock.moko.resources.desc.StringDesc
12+
import kotlinx.coroutines.DisposableHandle
13+
14+
fun <T : StringDesc?> TextView.bindText(
15+
lifecycleOwner: LifecycleOwner,
16+
flow: CStateFlow<T>
17+
): DisposableHandle {
18+
return flow.bind(lifecycleOwner) { this.text = it?.toString(this.context) }
19+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright 2022 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package dev.icerock.moko.mvvm.flow.resources
6+
7+
import dev.icerock.moko.mvvm.flow.CStateFlow
8+
import dev.icerock.moko.mvvm.flow.DisposableHandle
9+
import dev.icerock.moko.mvvm.flow.binding.bind
10+
import dev.icerock.moko.resources.desc.StringDesc
11+
import platform.UIKit.UIButton
12+
import platform.UIKit.UIControlStateNormal
13+
14+
fun <T : StringDesc?> UIButton.bindTitle(
15+
flow: CStateFlow<T>
16+
): DisposableHandle {
17+
return bind(flow) {
18+
this.setTitle(
19+
it?.localized(),
20+
forState = UIControlStateNormal
21+
)
22+
}
23+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright 2022 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package dev.icerock.moko.mvvm.flow.resources
6+
7+
import dev.icerock.moko.mvvm.flow.CStateFlow
8+
import dev.icerock.moko.mvvm.flow.DisposableHandle
9+
import dev.icerock.moko.mvvm.flow.binding.bind
10+
import dev.icerock.moko.resources.desc.StringDesc
11+
import platform.UIKit.UILabel
12+
13+
fun <T : StringDesc?> UILabel.bindText(
14+
flow: CStateFlow<T>
15+
): DisposableHandle {
16+
return bind(flow) { this.text = it?.localized() }
17+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright 2022 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package dev.icerock.moko.mvvm.flow.resources
6+
7+
import dev.icerock.moko.mvvm.flow.CStateFlow
8+
import dev.icerock.moko.mvvm.flow.DisposableHandle
9+
import dev.icerock.moko.mvvm.flow.binding.bind
10+
import dev.icerock.moko.resources.desc.StringDesc
11+
import platform.UIKit.UITextField
12+
13+
fun <T : StringDesc?> UITextField.bindText(
14+
flow: CStateFlow<T>
15+
): DisposableHandle {
16+
return bind(flow) { value ->
17+
val newValue = value?.localized().orEmpty()
18+
if (this.text == newValue) return@bind
19+
this.text = newValue
20+
}
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright 2022 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package dev.icerock.moko.mvvm.flow.resources
6+
7+
import dev.icerock.moko.mvvm.flow.CStateFlow
8+
import dev.icerock.moko.mvvm.flow.DisposableHandle
9+
import dev.icerock.moko.mvvm.flow.binding.bind
10+
import dev.icerock.moko.resources.desc.StringDesc
11+
import platform.UIKit.UITextView
12+
13+
fun <T : StringDesc?> UITextView.bindText(
14+
flow: CStateFlow<T>
15+
): DisposableHandle {
16+
return bind(flow) { value ->
17+
val newValue = value?.localized().orEmpty()
18+
if (this.text == newValue) return@bind
19+
this.text = newValue
20+
}
21+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
import dev.icerock.moko.mvvm.flow.cStateFlow
6+
import dev.icerock.moko.mvvm.flow.resources.bindTitle
7+
import dev.icerock.moko.resources.desc.StringDesc
8+
import dev.icerock.moko.resources.desc.desc
9+
import kotlinx.cinterop.readValue
10+
import kotlinx.coroutines.flow.MutableStateFlow
11+
import platform.CoreGraphics.CGRectZero
12+
import platform.UIKit.UIButton
13+
import kotlin.test.BeforeTest
14+
import kotlin.test.Ignore
15+
import kotlin.test.Test
16+
import kotlin.test.assertEquals
17+
18+
@Ignore
19+
class UIButtonBindingsTests {
20+
21+
private lateinit var destination: UIButton
22+
23+
@BeforeTest
24+
fun setup() {
25+
destination = UIButton(frame = CGRectZero.readValue())
26+
}
27+
28+
@Test
29+
fun `nonnullable stringdesc title`() {
30+
val source: MutableStateFlow<StringDesc> = MutableStateFlow("init".desc())
31+
destination.bindTitle(source.cStateFlow())
32+
assertEquals(
33+
expected = "init",
34+
actual = destination.currentTitle
35+
)
36+
source.value = "second".desc()
37+
assertEquals(
38+
expected = "second",
39+
actual = destination.currentTitle
40+
)
41+
}
42+
43+
@Test
44+
fun `nullable stringdesc title`() {
45+
val source: MutableStateFlow<StringDesc?> = MutableStateFlow(null)
46+
destination.bindTitle(source.cStateFlow())
47+
assertEquals(
48+
expected = null,
49+
actual = destination.currentTitle
50+
)
51+
source.value = "value".desc()
52+
assertEquals(
53+
expected = "value",
54+
actual = destination.currentTitle
55+
)
56+
}
57+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
import dev.icerock.moko.mvvm.flow.cStateFlow
6+
import dev.icerock.moko.mvvm.flow.resources.bindText
7+
import dev.icerock.moko.resources.desc.StringDesc
8+
import dev.icerock.moko.resources.desc.desc
9+
import kotlinx.cinterop.readValue
10+
import kotlinx.coroutines.flow.MutableStateFlow
11+
import platform.CoreGraphics.CGRectZero
12+
import platform.UIKit.UILabel
13+
import kotlin.test.BeforeTest
14+
import kotlin.test.Ignore
15+
import kotlin.test.Test
16+
import kotlin.test.assertEquals
17+
18+
@Ignore
19+
class UILabelBindingsTests {
20+
21+
private lateinit var destination: UILabel
22+
23+
@BeforeTest
24+
fun setup() {
25+
destination = UILabel(frame = CGRectZero.readValue())
26+
}
27+
28+
@Test
29+
fun `nonnullable stringdesc text`() {
30+
val source: MutableStateFlow<StringDesc> = MutableStateFlow("init".desc())
31+
destination.bindText(source.cStateFlow())
32+
assertEquals(
33+
expected = "init",
34+
actual = destination.text
35+
)
36+
source.value = "second".desc()
37+
assertEquals(
38+
expected = "second",
39+
actual = destination.text
40+
)
41+
}
42+
43+
@Test
44+
fun `nullable stringdesc text`() {
45+
val source: MutableStateFlow<StringDesc?> = MutableStateFlow(null)
46+
destination.bindText(source.cStateFlow())
47+
assertEquals(
48+
expected = null,
49+
actual = destination.text
50+
)
51+
source.value = "value".desc()
52+
assertEquals(
53+
expected = "value",
54+
actual = destination.text
55+
)
56+
}
57+
}

0 commit comments

Comments
 (0)