Skip to content
This repository has been archived by the owner on Jun 1, 2024. It is now read-only.

Commit

Permalink
feat: add support to bind in Display (#1086)
Browse files Browse the repository at this point in the history
* fix: parse color when is RGB size (#1033)

* fix: parse color when is RGB size

Signed-off-by: Matheus Ribeiro <matheus.ribeiro@zup.com.br>

* refactor: change method structure in ColorUtils.kt

Signed-off-by: Matheus Ribeiro <matheus.ribeiro@zup.com.br>

* refactor tests method names

Signed-off-by: Matheus Ribeiro <matheus.ribeiro@zup.com.br>

* fix: adjust http client default to handle exception when set body (#1050)

* remove shared code bettween backend and android

* adjust detekt

* refactor: move module kotlin-core to inside beagle to possible add bind in fields of core

* fix: adjust override title when navigate in screen (#1052)

* fix: adjust context evaluation to return correct types (#1043)

* refactor: remove deprecated from constructor

* fix: adjust name action backend

* fix: adjust serialization context

* adjust try serializer

* adjust context data manager

* adjust try to deserializer

* adjust unit tests

* adjust class

* remove space extra

* adjust test in form

* adjust evaluation

* adjust lint

* fix: adjust context data evaluation to enum

* adjust lint

* adjust suppor to bind

* remove module kotlin-core

* fix: adjust support to bind

* adjust code

* remove code used to test

* create unit test to mapper and flex view

* adjust import

* adjust function

* adjust layout change

* adjust unit test

* adjust unit test

* adjust unit test

Co-authored-by: Matheus Ribeiro Lima <57918064+matheusribeirozup@users.noreply.github.com>
Co-authored-by: viniciusguardieirozup <58824112+viniciusguardieirozup@users.noreply.github.com>
  • Loading branch information
3 people committed Oct 27, 2020
1 parent bd809a9 commit 32e93a2
Show file tree
Hide file tree
Showing 7 changed files with 245 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package br.com.zup.beagle.android.context

import br.com.zup.beagle.android.data.serializer.BeagleMoshi
import kotlin.reflect.KClass
import kotlin.reflect.full.isSubclassOf
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
Expand All @@ -31,14 +33,23 @@ internal fun ContextData.normalize(): ContextData {
}

internal fun Any.normalizeContextValue(): Any {
return if (isValueNormalized()) {
this
} else {
val newValue = BeagleMoshi.moshi.adapter(Any::class.java).toJson(this) ?: ""
newValue.normalizeContextValue()
return when {
isValueNormalized() -> {
this
}
isEnum(this::class) -> {
this.toString()
}
else -> {
val newValue = BeagleMoshi.moshi.adapter(Any::class.java).toJson(this) ?: ""
newValue.normalizeContextValue()
}
}
}

private fun isEnum(type: KClass<out Any>) = type.isSubclassOf(Enum::class)


internal fun String.normalizeContextValue(): Any {
return try {
JSONObject(this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@

package br.com.zup.beagle.android.engine.mapper

import android.view.View
import br.com.zup.beagle.android.utils.dp
import br.com.zup.beagle.android.utils.internalObserveBindChanges
import br.com.zup.beagle.android.widget.RootView
import br.com.zup.beagle.core.Style
import br.com.zup.beagle.widget.core.EdgeValue
import br.com.zup.beagle.widget.core.Size
Expand All @@ -31,7 +34,7 @@ import com.facebook.yoga.YogaNode
import com.facebook.yoga.YogaPositionType
import com.facebook.yoga.YogaWrap

class FlexMapper {
internal class FlexMapper {

fun makeYogaNode(style: Style): YogaNode = YogaNode.create().apply {
flexDirection = makeYogaFlexDirection(style.flex?.flexDirection) ?: YogaFlexDirection.COLUMN
Expand All @@ -40,16 +43,30 @@ class FlexMapper {
alignItems = makeYogaAlignItems(style.flex?.alignItems) ?: YogaAlign.STRETCH
alignSelf = makeYogaAlignSelf(style.flex?.alignSelf) ?: YogaAlign.AUTO
alignContent = makeYogaAlignContent(style.flex?.alignContent) ?: YogaAlign.FLEX_START
if(style.flex?.flex == null) {
if (style.flex?.flex == null) {
flexGrow = style.flex?.grow?.toFloat() ?: 0.0f
flexShrink = style.flex?.shrink?.toFloat() ?: 1.0f
}
style.flex?.flex?.toFloat()?.let { flex = it }
display = makeYogaDisplay(style.display) ?: YogaDisplay.FLEX

display = YogaDisplay.FLEX
positionType = makeYogaPositionType(style.positionType) ?: YogaPositionType.RELATIVE
applyAttributes(style, this)
}

fun observeBindChangesFlex(style: Style,
rootView: RootView,
view: View,
yogaNode: YogaNode) {

if (style.display != null) {
internalObserveBindChanges(rootView, view, style.display) {
yogaNode.display = makeYogaDisplay(it) ?: YogaDisplay.FLEX
view.requestLayout()
}
}
}

private fun applyAttributes(style: Style, yogaNode: YogaNode) {
setWidth(style.size, yogaNode)
setHeight(style.size, yogaNode)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,15 @@ fun <T> ServerDrivenComponent.observeBindChanges(
view: View,
bind: Bind<T>,
observes: Observer<T?>
) {
internalObserveBindChanges(rootView, view, bind, observes)
}

internal fun <T> internalObserveBindChanges(
rootView: RootView,
view: View,
bind: Bind<T>,
observes: Observer<T?>
) {
val value = bind.observe(rootView, view, observes)
if (bind is Bind.Value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ import br.com.zup.beagle.core.GhostComponent
import br.com.zup.beagle.core.ServerDrivenComponent
import br.com.zup.beagle.core.Style
import br.com.zup.beagle.core.StyleComponent
import com.facebook.yoga.YogaNode
import com.facebook.yoga.YogaNodeJNIBase

@Suppress("LeakingThis")
@SuppressLint("ViewConstructor")
internal open class BeagleFlexView(
private val rootView: RootView,
Expand All @@ -39,6 +41,10 @@ internal open class BeagleFlexView(
private val viewModel: ScreenContextViewModel = rootView.generateViewModelInstance()
) : YogaLayout(rootView.getContext(), flexMapper.makeYogaNode(style)) {

init {
observeStyleChanges(style, this, yogaNode)
}

constructor(
rootView: RootView,
flexMapper: FlexMapper = FlexMapper()
Expand All @@ -47,8 +53,7 @@ internal open class BeagleFlexView(
var listenerOnViewDetachedFromWindow: (() -> Unit)? = null

fun addView(child: View, style: Style) {

super.addView(child, flexMapper.makeYogaNode(style))
addViewWithBind(style, child, this)
}

fun addServerDrivenComponent(serverDrivenComponent: ServerDrivenComponent,
Expand All @@ -65,7 +70,17 @@ internal open class BeagleFlexView(
(yogaNode as YogaNodeJNIBase).dirtyAllDescendants()
}
}
super.addView(view, flexMapper.makeYogaNode(style))
addViewWithBind(style, view, view)
}

private fun addViewWithBind(style: Style, child: View, viewBind: View){
val childYogaNode = flexMapper.makeYogaNode(style)
observeStyleChanges(style, viewBind, childYogaNode)
super.addView(child, childYogaNode)
}

private fun observeStyleChanges(style: Style, view: View, yogaNode: YogaNode) {
flexMapper.observeBindChangesFlex(style, rootView, view, yogaNode)
}

override fun onAttachedToWindow() {
Expand Down
3 changes: 2 additions & 1 deletion android/beagle/src/main/java/br/com/zup/beagle/core/Style.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package br.com.zup.beagle.core

import br.com.zup.beagle.android.context.Bind
import br.com.zup.beagle.widget.core.EdgeValue
import br.com.zup.beagle.widget.core.Flex
import br.com.zup.beagle.widget.core.Size
Expand Down Expand Up @@ -59,7 +60,7 @@ data class Style (
val position: EdgeValue? = null,
val flex: Flex? = null,
val positionType: PositionType? = null,
val display: Display? = null
val display: Bind<Display>? = null
)

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,13 @@

package br.com.zup.beagle.android.engine.mapper

import android.view.View
import br.com.zup.beagle.android.context.valueOf
import br.com.zup.beagle.android.extensions.once
import br.com.zup.beagle.android.utils.Observer
import br.com.zup.beagle.android.utils.dp
import br.com.zup.beagle.android.utils.internalObserveBindChanges
import br.com.zup.beagle.android.widget.RootView
import br.com.zup.beagle.core.Display
import br.com.zup.beagle.core.Style
import br.com.zup.beagle.widget.core.AlignContent
Expand All @@ -40,12 +45,16 @@ import com.facebook.yoga.YogaNode
import com.facebook.yoga.YogaWrap
import io.mockk.MockKAnnotations
import io.mockk.Runs
import io.mockk.clearStaticMockk
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.just
import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.slot
import io.mockk.unmockkAll
import io.mockk.verify
import io.mockk.verifyOrder
import io.mockk.verifySequence
import kotlin.test.assertFalse
import org.junit.After
import org.junit.Before
import org.junit.Test
Expand All @@ -55,8 +64,11 @@ private const val ONE_UNIT_VALUE = 1.0

class FlexMapperTest {

@MockK
private lateinit var yogaNode: YogaNode
private val yogaNodeMock: YogaNode = mockk(relaxed = true, relaxUnitFun = true)
private val rootViewMock: RootView = mockk()
private val viewMock: View = mockk(relaxUnitFun = true, relaxed = true)

private val observeSlot = slot<Observer<Display?>>()

private lateinit var flexMapper: FlexMapper

Expand All @@ -68,48 +80,25 @@ class FlexMapperTest {

mockkStatic(YogaNode::class)
mockkStatic("br.com.zup.beagle.android.utils.NumberExtensionsKt")
mockkStatic("br.com.zup.beagle.android.utils.WidgetExtensionsKt")

every {
internalObserveBindChanges(
rootView = rootViewMock,
view = viewMock,
bind = any(),
observes = capture(observeSlot)
)
} just Runs

every { HUNDRED_UNIT_VALUE.dp() } returns HUNDRED_UNIT_VALUE
every { ONE_UNIT_VALUE.dp() } returns ONE_UNIT_VALUE
every { YogaNode.create() } returns yogaNode
every { yogaNode.flexDirection = any() } just Runs
every { yogaNode.wrap = any() } just Runs
every { yogaNode.justifyContent = any() } just Runs
every { yogaNode.alignItems = any() } just Runs
every { yogaNode.alignSelf = any() } just Runs
every { yogaNode.alignContent = any() } just Runs
every { yogaNode.flex = any() } just Runs
every { yogaNode.flexGrow = any() } just Runs
every { yogaNode.flexShrink = any() } just Runs
every { yogaNode.display = any() } just Runs
every { yogaNode.aspectRatio = any() } just Runs
every { yogaNode.positionType = any() } just Runs
every { yogaNode.setWidth(any()) } just Runs
every { yogaNode.setWidthPercent(any()) } just Runs
every { yogaNode.setHeight(any()) } just Runs
every { yogaNode.setHeightPercent(any()) } just Runs
every { yogaNode.setMaxWidth(any()) } just Runs
every { yogaNode.setMaxWidthPercent(any()) } just Runs
every { yogaNode.setMaxHeight(any()) } just Runs
every { yogaNode.setMaxHeightPercent(any()) } just Runs
every { yogaNode.setMinWidth(any()) } just Runs
every { yogaNode.setMinWidthPercent(any()) } just Runs
every { yogaNode.setMinHeight(any()) } just Runs
every { yogaNode.setMinHeightPercent(any()) } just Runs
every { yogaNode.setFlexBasis(any()) } just Runs
every { yogaNode.setFlexBasisPercent(any()) } just Runs
every { yogaNode.setMargin(any(), any()) } just Runs
every { yogaNode.setMarginPercent(any(), any()) } just Runs
every { yogaNode.setPadding(any(), any()) } just Runs
every { yogaNode.setPaddingPercent(any(), any()) } just Runs
every { yogaNode.setPosition(any(), any()) } just Runs
every { yogaNode.setPositionPercent(any(), any()) } just Runs
every { yogaNode.setFlexBasisAuto() } just Runs
every { YogaNode.create() } returns yogaNodeMock
}

@After
fun tearDown() {
clearStaticMockk()
unmockkAll()
}

@Test
Expand Down Expand Up @@ -197,7 +186,7 @@ class FlexMapperTest {
}

@Test
fun makeYogaNode_should_set_flex_as_1(){
fun makeYogaNode_should_set_flex_as_1() {
//Given
val flex = Flex(
flex = ONE_UNIT_VALUE
Expand All @@ -207,7 +196,7 @@ class FlexMapperTest {
val yogaNode = flexMapper.makeYogaNode(Style(flex = flex))

//Then
verify (exactly = once()) { yogaNode.flex = ONE_UNIT_VALUE.toFloat() }
verify(exactly = once()) { yogaNode.flex = ONE_UNIT_VALUE.toFloat() }
}

@Test
Expand Down Expand Up @@ -239,31 +228,53 @@ class FlexMapperTest {
}

@Test
fun makeYogaNode_should_set_display_as_FLEX() {
fun `GIVEN display NONE WHEN call observe bind changes THEN it should set in yoga node correct display`() {
// Given
val style = Style(
display = Display.FLEX
display = valueOf(Display.NONE)
)

// When
val yogaNode = flexMapper.makeYogaNode(style)
flexMapper.observeBindChangesFlex(style, rootViewMock, viewMock, yogaNodeMock)
observeSlot.captured.invoke(Display.NONE)

// Then
verify(exactly = once()) { yogaNode.display = YogaDisplay.FLEX }
verifyOrder {
yogaNodeMock.display = YogaDisplay.NONE
viewMock.requestLayout()
}
}

@Test
fun makeYogaNode_should_set_display_as_NONE() {
fun `GIVEN display FLEX WHEN call observe bind changes THEN it should set in yoga node correct display`() {
// Given
val style = Style(
display = Display.NONE
display = valueOf(Display.FLEX)
)

// When
val yogaNode = flexMapper.makeYogaNode(style)
flexMapper.observeBindChangesFlex(style, rootViewMock, viewMock, yogaNodeMock)
observeSlot.captured.invoke(Display.FLEX)

// Then
verifyOrder {
yogaNodeMock.display = YogaDisplay.FLEX
viewMock.requestLayout()
}
}

@Test
fun `GIVEN display NULL WHEN call observe bind changes THEN it should never call bind changes`() {
// Given
val style = Style(
display = null
)

// When
flexMapper.observeBindChangesFlex(style, rootViewMock, viewMock, yogaNodeMock)

// Then
verify(exactly = once()) { yogaNode.display = YogaDisplay.NONE }
assertFalse(observeSlot.isCaptured)
}

@Test
Expand Down

0 comments on commit 32e93a2

Please sign in to comment.