diff --git a/.mapping.json b/.mapping.json index 85c300821..b7352a0a0 100644 --- a/.mapping.json +++ b/.mapping.json @@ -602,12 +602,12 @@ "client/android/compose-interop/src/main/java/com/yandex/div/compose/interop/DivViewInterop.kt":"divkit/public/client/android/compose-interop/src/main/java/com/yandex/div/compose/interop/DivViewInterop.kt", "client/android/compose/build.gradle.kts":"divkit/public/client/android/compose/build.gradle.kts", "client/android/compose/proguard-rules.pro":"divkit/public/client/android/compose/proguard-rules.pro", + "client/android/compose/src/androidTest/kotlin/com/yandex/div/compose/DivViewPreview.kt":"divkit/public/client/android/compose/src/androidTest/kotlin/com/yandex/div/compose/DivViewPreview.kt", "client/android/compose/src/main/kotlin/com/yandex/div/compose/DivComposeConfiguration.kt":"divkit/public/client/android/compose/src/main/kotlin/com/yandex/div/compose/DivComposeConfiguration.kt", "client/android/compose/src/main/kotlin/com/yandex/div/compose/DivContext.kt":"divkit/public/client/android/compose/src/main/kotlin/com/yandex/div/compose/DivContext.kt", "client/android/compose/src/main/kotlin/com/yandex/div/compose/DivException.kt":"divkit/public/client/android/compose/src/main/kotlin/com/yandex/div/compose/DivException.kt", "client/android/compose/src/main/kotlin/com/yandex/div/compose/DivReporter.kt":"divkit/public/client/android/compose/src/main/kotlin/com/yandex/div/compose/DivReporter.kt", "client/android/compose/src/main/kotlin/com/yandex/div/compose/DivView.kt":"divkit/public/client/android/compose/src/main/kotlin/com/yandex/div/compose/DivView.kt", - "client/android/compose/src/main/kotlin/com/yandex/div/compose/DivViewPreview.kt":"divkit/public/client/android/compose/src/main/kotlin/com/yandex/div/compose/DivViewPreview.kt", "client/android/compose/src/main/kotlin/com/yandex/div/compose/actions/DivActionData.kt":"divkit/public/client/android/compose/src/main/kotlin/com/yandex/div/compose/actions/DivActionData.kt", "client/android/compose/src/main/kotlin/com/yandex/div/compose/actions/DivActionHandler.kt":"divkit/public/client/android/compose/src/main/kotlin/com/yandex/div/compose/actions/DivActionHandler.kt", "client/android/compose/src/main/kotlin/com/yandex/div/compose/actions/DivActionHandlingContext.kt":"divkit/public/client/android/compose/src/main/kotlin/com/yandex/div/compose/actions/DivActionHandlingContext.kt", @@ -1839,20 +1839,16 @@ "client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/steps/VisibilityActionsSteps.kt":"divkit/public/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/steps/VisibilityActionsSteps.kt", "client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/utils/CharSequences.kt":"divkit/public/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/utils/CharSequences.kt", "client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/utils/OutsideActions.kt":"divkit/public/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/utils/OutsideActions.kt", - "client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/utils/UiTestDivActionHandler.kt":"divkit/public/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/utils/UiTestDivActionHandler.kt", "client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/utils/Utils.kt":"divkit/public/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/utils/Utils.kt", "client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/utils/ViewCoordinatesHelper.kt":"divkit/public/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/utils/ViewCoordinatesHelper.kt", "client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/utils/ViewInteractionExt.kt":"divkit/public/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/utils/ViewInteractionExt.kt", "client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/utils/ViewPagerActions.kt":"divkit/public/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/utils/ViewPagerActions.kt", - "client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/TextView.kt":"divkit/public/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/TextView.kt", "client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/Utils.kt":"divkit/public/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/Utils.kt", "client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewActions.kt":"divkit/public/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewActions.kt", "client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewAssertions.kt":"divkit/public/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewAssertions.kt", "client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewInteraction.kt":"divkit/public/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewInteraction.kt", "client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewMatchers.kt":"divkit/public/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewMatchers.kt", "client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/actions/ExtendedScrollTo.kt":"divkit/public/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/actions/ExtendedScrollTo.kt", - "client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/getThemeColor.kt":"divkit/public/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/getThemeColor.kt", - "client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/viewHelpers.kt":"divkit/public/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/viewHelpers.kt", "client/android/divkit-demo-app/src/debug/AndroidManifest.xml":"divkit/public/client/android/divkit-demo-app/src/debug/AndroidManifest.xml", "client/android/divkit-demo-app/src/main/AndroidManifest.xml":"divkit/public/client/android/divkit-demo-app/src/main/AndroidManifest.xml", "client/android/divkit-demo-app/src/main/assets/application/demo.json":"divkit/public/client/android/divkit-demo-app/src/main/assets/application/demo.json", @@ -2007,7 +2003,6 @@ "client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/DivkitDemoPermissionHelper.kt":"divkit/public/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/DivkitDemoPermissionHelper.kt", "client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/DivkitDemoUriHandler.kt":"divkit/public/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/DivkitDemoUriHandler.kt", "client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/HttpUtil.kt":"divkit/public/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/HttpUtil.kt", - "client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/JsonAssetReader.kt":"divkit/public/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/JsonAssetReader.kt", "client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/MetricaUtils.kt":"divkit/public/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/MetricaUtils.kt", "client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/QRCaptureActivity.kt":"divkit/public/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/QRCaptureActivity.kt", "client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/Toasts.kt":"divkit/public/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/Toasts.kt", @@ -17187,6 +17182,7 @@ "client/android/test-utils/src/main/kotlin/com/yandex/div/test/crossplatform/ParsingResult.kt":"divkit/public/client/android/test-utils/src/main/kotlin/com/yandex/div/test/crossplatform/ParsingResult.kt", "client/android/test-utils/src/main/kotlin/com/yandex/div/test/crossplatform/ParsingUtils.kt":"divkit/public/client/android/test-utils/src/main/kotlin/com/yandex/div/test/crossplatform/ParsingUtils.kt", "client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivActionUtils.kt":"divkit/public/client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivActionUtils.kt", + "client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivBackgroundUtils.kt":"divkit/public/client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivBackgroundUtils.kt", "client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivContainerUtils.kt":"divkit/public/client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivContainerUtils.kt", "client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivDataUtils.kt":"divkit/public/client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivDataUtils.kt", "client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivTextUtils.kt":"divkit/public/client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivTextUtils.kt", diff --git a/client/android/compose-interop/build.gradle b/client/android/compose-interop/build.gradle index e407bb62d..cfae54abe 100644 --- a/client/android/compose-interop/build.gradle +++ b/client/android/compose-interop/build.gradle @@ -26,10 +26,7 @@ dependencies { implementation platform(libs.androidx.compose.bom) implementation libs.androidx.compose.foundation - implementation libs.androidx.compose.ui.tooling.preview implementation libs.androidx.core - - debugImplementation libs.androidx.compose.ui.tooling } tasks.withType(KotlinCompile).configureEach { diff --git a/client/android/compose/build.gradle.kts b/client/android/compose/build.gradle.kts index 1b287bc3f..2625cb28a 100644 --- a/client/android/compose/build.gradle.kts +++ b/client/android/compose/build.gradle.kts @@ -9,6 +9,10 @@ apply(from = "../div-tests.gradle") android { namespace = "com.yandex.div.compose" + + defaultConfig { + minSdk = 23 + } } dependencies { @@ -19,7 +23,6 @@ dependencies { implementation(platform(libs.androidx.compose.bom)) implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling.preview) implementation(libs.androidx.coreKtx) implementation(libs.coil.compose) implementation(libs.coil.network) @@ -29,6 +32,9 @@ dependencies { debugImplementation(libs.androidx.compose.ui.tooling) + androidTestImplementation(project(":test-utils")) + androidTestImplementation(libs.androidx.compose.ui.tooling.preview) + testImplementation(project(":test-utils")) testImplementation(libs.androidx.compose.ui.test.junit4) testImplementation(libs.androidx.compose.ui.test.manifest) diff --git a/client/android/compose/src/androidTest/kotlin/com/yandex/div/compose/DivViewPreview.kt b/client/android/compose/src/androidTest/kotlin/com/yandex/div/compose/DivViewPreview.kt new file mode 100644 index 000000000..db23b11ef --- /dev/null +++ b/client/android/compose/src/androidTest/kotlin/com/yandex/div/compose/DivViewPreview.kt @@ -0,0 +1,62 @@ +package com.yandex.div.compose + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.tooling.preview.Preview +import com.yandex.div.test.data.action +import com.yandex.div.test.data.color +import com.yandex.div.test.data.constant +import com.yandex.div.test.data.container +import com.yandex.div.test.data.data +import com.yandex.div.test.data.expression +import com.yandex.div.test.data.setVariableAction +import com.yandex.div.test.data.solidBackground +import com.yandex.div.test.data.text +import com.yandex.div.test.data.typedValue +import com.yandex.div.test.data.variable +import com.yandex.div2.DivEdgeInsets + +@Preview +@Composable +fun DivViewPreview() { + val divContext = DivComposeConfiguration() + .createContext(baseContext = LocalContext.current) + CompositionLocalProvider(LocalContext provides divContext) { + DivView(data = testData) + } +} + +private val testData = data( + content = container( + backgrounds = listOf( + solidBackground(color = color(0xFF90C090)) + ), + items = listOf( + text( + action = action( + typed = setVariableAction( + name = "title", + value = typedValue("New Title") + ) + ), + fontSize = 36, + text = expression("@{title}"), + textColor = color(0xFFBF0000) + ) + ), + margins = DivEdgeInsets( + top = constant(10), + bottom = constant(10) + ), + paddings = DivEdgeInsets( + start = constant(10), + end = constant(10), + top = constant(20), + bottom = constant(20) + ) + ), + variables = listOf( + variable(name = "title", value = "Hello!") + ) +) diff --git a/client/android/compose/src/main/kotlin/com/yandex/div/compose/DivViewPreview.kt b/client/android/compose/src/main/kotlin/com/yandex/div/compose/DivViewPreview.kt deleted file mode 100644 index 879258da3..000000000 --- a/client/android/compose/src/main/kotlin/com/yandex/div/compose/DivViewPreview.kt +++ /dev/null @@ -1,107 +0,0 @@ -package com.yandex.div.compose - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.tooling.preview.Preview -import com.yandex.div.internal.parser.TYPE_HELPER_STRING -import com.yandex.div.json.ParsingErrorLogger -import com.yandex.div.json.expressions.Expression -import com.yandex.div2.Div -import com.yandex.div2.DivAction -import com.yandex.div2.DivActionSetVariable -import com.yandex.div2.DivActionTyped -import com.yandex.div2.DivBackground -import com.yandex.div2.DivContainer -import com.yandex.div2.DivData -import com.yandex.div2.DivEdgeInsets -import com.yandex.div2.DivSolidBackground -import com.yandex.div2.DivText -import com.yandex.div2.DivTypedValue -import com.yandex.div2.DivVariable -import com.yandex.div2.StrValue -import com.yandex.div2.StrVariable - -@Preview -@Composable -private fun DivViewPreview() { - val divContext = DivComposeConfiguration() - .createContext(baseContext = LocalContext.current) - CompositionLocalProvider(LocalContext provides divContext) { - DivView(data = testData) - } -} - -private val testData = DivData( - logId = "preview", - variables = listOf( - DivVariable.Str( - StrVariable( - name = "title", - value = constant("Hello!") - ) - ) - ), - states = listOf( - DivData.State( - stateId = 0, - div = Div.Container( - value = DivContainer( - orientation = constant(DivContainer.Orientation.VERTICAL), - paddings = DivEdgeInsets( - start = constant(10), - end = constant(10), - top = constant(20), - bottom = constant(20) - ), - margins = DivEdgeInsets( - top = constant(10), - bottom = constant(10) - ), - background = listOf( - DivBackground.Solid( - value = DivSolidBackground( - color = constant(0xFF909090.toInt()), - ) - ) - ), - items = listOf( - Div.Text( - value = DivText( - action = DivAction( - logId = constant("test"), - typed = DivActionTyped.SetVariable( - DivActionSetVariable( - variableName = constant("title"), - value = DivTypedValue.Str( - StrValue(value = constant("New Title")) - ) - ) - ) - ), - fontSize = constant(36), - text = expression("@{title}"), - textColor = constant(0xFFBF0000.toInt()), - ) - ) - ) - ) - ) - ) - ) -) - -private fun constant(value: T): Expression { - return Expression.ConstantExpression(value) -} - -private fun expression(expression: String): Expression { - return Expression.MutableExpression( - expressionKey = "test", - rawExpression = expression, - converter = null, - validator = { true }, - logger = ParsingErrorLogger.ASSERT, - typeHelper = TYPE_HELPER_STRING - ) -} diff --git a/client/android/div/src/test/java/com/yandex/div/core/DivPreloaderTest.kt b/client/android/div/src/test/java/com/yandex/div/core/DivPreloaderTest.kt index 2528b6b05..7618f1369 100644 --- a/client/android/div/src/test/java/com/yandex/div/core/DivPreloaderTest.kt +++ b/client/android/div/src/test/java/com/yandex/div/core/DivPreloaderTest.kt @@ -44,7 +44,7 @@ class DivPreloaderTest { private val extensionHandlers = listOf(mock(), mock()) private val extensionHandlersController = DivExtensionController(extensionHandlers) - private val divText = text(text = constant("test")) + private val divText = text(text = "test") private val custom = DivCustom(customType = "test") private val divCustom = Div.Custom(custom) diff --git a/client/android/div/src/test/java/com/yandex/div/core/util/DivWalkTreeTest.kt b/client/android/div/src/test/java/com/yandex/div/core/util/DivWalkTreeTest.kt index e9d587ad9..ab2d2b8de 100644 --- a/client/android/div/src/test/java/com/yandex/div/core/util/DivWalkTreeTest.kt +++ b/client/android/div/src/test/java/com/yandex/div/core/util/DivWalkTreeTest.kt @@ -4,10 +4,10 @@ import android.net.Uri import com.yandex.div.core.asExpression import com.yandex.div.core.mockExpressionResolver import com.yandex.div.test.data.container +import com.yandex.div.test.data.text import com.yandex.div2.Div import com.yandex.div2.DivGallery import com.yandex.div2.DivImage -import com.yandex.div2.DivText import org.junit.Assert.assertEquals import org.junit.Test import org.junit.runner.RunWith @@ -20,7 +20,7 @@ class DivWalkTreeTest { @Test fun `walking single node hierarchy`() { - val rootDiv = divText("lorem ipsum") + val rootDiv = text(text = "lorem ipsum") val divWalk = rootDiv.walk(resolver) .map { item -> item.div.type } @@ -31,8 +31,8 @@ class DivWalkTreeTest { @Test fun `walking multiple node hierarchy`() { val rootDiv = container( - listOf( - divText("lorem ipsum"), + items = listOf( + text(text = "lorem ipsum"), divImage("https://none") ) ) @@ -46,14 +46,14 @@ class DivWalkTreeTest { @Test fun `walking uses depth-first order`() { val rootDiv = container( - listOf( + items = listOf( container( - listOf( - divText("lorem ipsum"), + items = listOf( + text(text = "lorem ipsum"), divImage("https://none") ) ), - divText("lorem ipsum") + text(text = "lorem ipsum") ) ) @@ -66,14 +66,14 @@ class DivWalkTreeTest { @Test fun `onEnter excludes subtree from walking`() { val rootDiv = container( - listOf( + items = listOf( divGallery( listOf( - divText("lorem ipsum"), + text(text = "lorem ipsum"), divImage("https://none") ) ), - divText("lorem ipsum") + text(text = "lorem ipsum") ) ) @@ -87,11 +87,11 @@ class DivWalkTreeTest { @Test fun `maxDepth limits walk depth`() { val rootDiv = container( - listOf( - divText("lorem ipsum"), + items = listOf( + text(text = "lorem ipsum"), container( - listOf( - divText("lorem ipsum"), + items = listOf( + text(text = "lorem ipsum"), divImage("https://none") ) ) @@ -108,11 +108,11 @@ class DivWalkTreeTest { @Test fun `onEnter() called only for branch nodes`() { val rootDiv = container( - listOf( - divText("lorem ipsum"), + items = listOf( + text(text = "lorem ipsum"), divGallery( listOf( - divText("lorem ipsum"), + text(text = "lorem ipsum"), divImage("https://none") ) ) @@ -133,11 +133,11 @@ class DivWalkTreeTest { @Test fun `onLeave() called only for branch nodes`() { val rootDiv = container( - listOf( - divText("lorem ipsum"), + items = listOf( + text(text = "lorem ipsum"), divGallery( listOf( - divText("lorem ipsum"), + text(text = "lorem ipsum"), divImage("https://none") ) ) @@ -152,10 +152,6 @@ class DivWalkTreeTest { assertEquals(listOf("gallery", "container"), leftDivs) } - private fun divText(text: String): Div { - return Div.Text(DivText(text = text.asExpression())) - } - private fun divImage(imageUrl: String): Div { return Div.Image(DivImage(imageUrl = Uri.parse(imageUrl).asExpression())) } diff --git a/client/android/div/src/test/java/com/yandex/div/core/view2/DivVisibilityActionTrackerTest.kt b/client/android/div/src/test/java/com/yandex/div/core/view2/DivVisibilityActionTrackerTest.kt index d33a1e42d..e57e34baf 100644 --- a/client/android/div/src/test/java/com/yandex/div/core/view2/DivVisibilityActionTrackerTest.kt +++ b/client/android/div/src/test/java/com/yandex/div/core/view2/DivVisibilityActionTrackerTest.kt @@ -66,11 +66,11 @@ class DivVisibilityActionTrackerTest { ) }.toList() - private val div1 = text(text = constant("test1"), visibilityActions = listOf(action1)) - private val div2 = text(text = constant("test2"), visibilityActions = listOf(action2)) - private val div3 = text(text = constant("test3"), visibilityActions = lottaActions) - private val div4 = text(text = constant("test4"), visibilityActions = actionsWithThreeDifferentDelays) - private val div5 = text(text = constant("test5"), visibilityActions = listOf(action1), disappearActions = listOf(disappearAction1)) + private val div1 = text(text = "test1", visibilityActions = listOf(action1)) + private val div2 = text(text = "test2", visibilityActions = listOf(action2)) + private val div3 = text(text = "test3", visibilityActions = lottaActions) + private val div4 = text(text = "test4", visibilityActions = actionsWithThreeDifferentDelays) + private val div5 = text(text = "test5", visibilityActions = listOf(action1), disappearActions = listOf(disappearAction1)) private val visibilityActionTracker = DivVisibilityActionTracker( viewVisibilityCalculator, diff --git a/client/android/div/src/test/java/com/yandex/div/core/view2/animations/DivComparatorTest.kt b/client/android/div/src/test/java/com/yandex/div/core/view2/animations/DivComparatorTest.kt index fb30620c0..fdd50d240 100644 --- a/client/android/div/src/test/java/com/yandex/div/core/view2/animations/DivComparatorTest.kt +++ b/client/android/div/src/test/java/com/yandex/div/core/view2/animations/DivComparatorTest.kt @@ -3,9 +3,9 @@ package com.yandex.div.core.view2.animations import android.net.Uri import com.yandex.div.core.asExpression import com.yandex.div.core.mockExpressionResolver +import com.yandex.div.test.data.container import com.yandex.div2.Div import com.yandex.div2.DivAppearanceTransition -import com.yandex.div2.DivContainer import com.yandex.div2.DivCustom import com.yandex.div2.DivGallery import com.yandex.div2.DivGrid @@ -83,48 +83,48 @@ class DivComparatorTest { @Test fun `containers with similar hierarchy are replaceable`() { - val div1 = divContainer(items = listOf(divText(text = "Text 01"))) - val div2 = divContainer(items = listOf(divText(text = "Text 02"))) + val div1 = container(items = listOf(divText(text = "Text 01"))) + val div2 = container(items = listOf(divText(text = "Text 02"))) assertTrue(DivComparator.areDivsReplaceable(div1, div2, resolver, resolver)) } @Test fun `containers with different child count are not replaceable`() { - val div1 = divContainer(items = listOf(divText(text = "Text 01"), divImage(imageUrl = "https://image"))) - val div2 = divContainer(items = listOf(divText(text = "Text 02"))) + val div1 = container(items = listOf(divText(text = "Text 01"), divImage(imageUrl = "https://image"))) + val div2 = container(items = listOf(divText(text = "Text 02"))) assertFalse(DivComparator.areDivsReplaceable(div1, div2, resolver, resolver)) } @Test fun `containers with different child types are not replaceable`() { - val div1 = divContainer(items = listOf(divImage(imageUrl = "https://image"))) - val div2 = divContainer(items = listOf(divText(text = "Text"))) + val div1 = container(items = listOf(divImage(imageUrl = "https://image"))) + val div2 = container(items = listOf(divText(text = "Text"))) assertFalse(DivComparator.areDivsReplaceable(div1, div2, resolver, resolver)) } @Test fun `containers with different child order are not replaceable`() { - val div1 = divContainer(items = listOf(divImage(imageUrl = "https://image"), divText(text = "Text 01"))) - val div2 = divContainer(items = listOf(divText(text = "Text 02"), divImage(imageUrl = "https://image"))) + val div1 = container(items = listOf(divImage(imageUrl = "https://image"), divText(text = "Text 01"))) + val div2 = container(items = listOf(divText(text = "Text 02"), divImage(imageUrl = "https://image"))) assertFalse(DivComparator.areDivsReplaceable(div1, div2, resolver, resolver)) } @Test fun `containers with different child ids are replaceable`() { - val div1 = divContainer(items = listOf(divText(id = "01", text = "Text 01"))) - val div2 = divContainer(items = listOf(divText(id = "02", text = "Text 02"))) + val div1 = container(items = listOf(divText(id = "01", text = "Text 01"))) + val div2 = container(items = listOf(divText(id = "02", text = "Text 02"))) assertTrue(DivComparator.areDivsReplaceable(div1, div2, resolver, resolver)) } @Test fun `containers which children has transitions and different ids are not replaceable`() { - val div1 = divContainer(items = listOf(divText(id = "01", text = "Text 01", transitionIn = transitionMock))) - val div2 = divContainer(items = listOf(divText(id = "02", text = "Text 02", transitionIn = transitionMock))) + val div1 = container(items = listOf(divText(id = "01", text = "Text 01", transitionIn = transitionMock))) + val div2 = container(items = listOf(divText(id = "02", text = "Text 02", transitionIn = transitionMock))) assertFalse(DivComparator.areDivsReplaceable(div1, div2, resolver, resolver)) } @@ -235,20 +235,6 @@ class DivComparatorTest { return Div.Custom(DivCustom(customType = type, transitionIn = transitionIn)) } - private fun divContainer( - orientation: DivContainer.Orientation = DivContainer.Orientation.VERTICAL, - items: List
, - transitionIn: DivAppearanceTransition? = null - ): Div { - return Div.Container( - DivContainer( - orientation = orientation.asExpression(), - items = items, - transitionIn = transitionIn - ) - ) - } - private fun divGrid(items: List
, transitionIn: DivAppearanceTransition? = null): Div { return Div.Grid( DivGrid( diff --git a/client/android/divkit-demo-app/build.gradle b/client/android/divkit-demo-app/build.gradle index 8894a983e..ee7026a48 100644 --- a/client/android/divkit-demo-app/build.gradle +++ b/client/android/divkit-demo-app/build.gradle @@ -25,6 +25,8 @@ android { } defaultConfig { + minSdk = 23 + versionCode = divkitVersion.versionCode + divkitVersion.buildNumber buildConfigField "int", "BUILD_NUMBER", "${divkitVersion.buildNumber}" buildConfigField "String", "METRICA_API_KEY", JsonOutput.toJson(providers.gradleProperty("metricaApiKey").getOrElse("")) diff --git a/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/utils/UiTestDivActionHandler.kt b/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/utils/UiTestDivActionHandler.kt deleted file mode 100644 index 5dfd865c5..000000000 --- a/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/utils/UiTestDivActionHandler.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.yandex.div.utils - -import android.net.Uri -import com.yandex.div.core.DivActionHandler -import com.yandex.div.core.DivViewFacade -import com.yandex.div.json.expressions.ExpressionResolver -import com.yandex.div2.DivAction - -private const val DIV_UI_TEST_SCHEME = "ui-test" -private const val CLICK_ACTION_HOST = "click" -private const val CLICK_TYPE_PARAM = "type" -private const val CLICK_DESCRIPTION_PARAM = "description" - -class UiTestDivActionHandler( - private val onClick: ((clickType: String, description: String) -> Unit)? = null -) : DivActionHandler() { - override fun handleAction(action: DivAction, view: DivViewFacade, resolver: ExpressionResolver): Boolean { - val url = action.url?.evaluate(resolver) ?: return false - if (url.scheme == DIV_UI_TEST_SCHEME) { - handleDemoActionUrl(url, view) - return true - } - return super.handleAction(action, view, resolver) - } - - private fun handleDemoActionUrl(url: Uri, view: DivViewFacade) { - if (url.host == CLICK_ACTION_HOST) { - val clickType = url.getQueryParameter(CLICK_TYPE_PARAM) - val description = url.getQueryParameter(CLICK_DESCRIPTION_PARAM) - if (clickType != null && description != null) { - onClick?.invoke(clickType, description) - } - } - } -} diff --git a/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/TextView.kt b/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/TextView.kt deleted file mode 100644 index 3fd4cac4e..000000000 --- a/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/TextView.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.yandex.div.view - -import android.text.Spanned -import android.text.style.ClickableSpan -import android.view.View -import android.widget.EditText -import android.widget.TextView -import androidx.core.text.getSpans -import androidx.test.espresso.UiController -import androidx.test.espresso.ViewAction -import androidx.test.espresso.matcher.ViewMatchers.assertThat -import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom -import androidx.test.espresso.matcher.ViewMatchers.isDisplayed -import org.hamcrest.Matcher -import org.hamcrest.Matchers.allOf -import org.hamcrest.Matchers.notNullValue - -object TextViewActions { - - /** - * Clear text in TextView - */ - fun clearText(): ViewAction { - return object : ViewAction { - - override fun getConstraints(): Matcher = allOf(isDisplayed(), isAssignableFrom(EditText::class.java)) - - override fun getDescription(): String = "Delete all text in EditText" - - override fun perform(uiController: UiController, view: View) { - uiController.loopMainThreadUntilIdle() - (view as EditText).text.clear() - } - } - } - - /** - * Taps a first found link if it is recognized. - */ - fun tapLink(): ViewAction { - return object : ViewAction { - - override fun getConstraints(): Matcher = allOf(isDisplayed(), isAssignableFrom(TextView::class.java)) - - override fun getDescription(): String = "Tap on link inside text" - - override fun perform(uiController: UiController, view: View) { - val spannable = (view as TextView).text as? Spanned - assertThat("Unknown text format found in $spannable", spannable, notNullValue()) - val span = spannable?.getSpans()?.firstOrNull() - assertThat("No link found in $spannable", spannable, notNullValue()) - span?.onClick(view) - } - } - } -} diff --git a/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewActions.kt b/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewActions.kt index e8480c252..8379244ec 100644 --- a/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewActions.kt +++ b/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewActions.kt @@ -2,52 +2,22 @@ package com.yandex.div.view -import android.view.InputDevice -import android.view.MotionEvent import android.view.View -import androidx.annotation.IdRes import androidx.test.espresso.Espresso.onView import androidx.test.espresso.NoMatchingViewException -import androidx.test.espresso.PerformException import androidx.test.espresso.UiController import androidx.test.espresso.ViewAction import androidx.test.espresso.ViewInteraction -import androidx.test.espresso.action.GeneralClickAction -import androidx.test.espresso.action.GeneralLocation -import androidx.test.espresso.action.Press -import androidx.test.espresso.action.Tap -import androidx.test.espresso.action.ViewActions -import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom import androidx.test.espresso.matcher.ViewMatchers.isClickable -import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed -import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.isRoot -import androidx.test.espresso.util.HumanReadables import androidx.test.espresso.util.TreeIterables import com.yandex.div.view.ViewMatchers.isDisplayedForClicking import org.hamcrest.Matcher import org.hamcrest.Matchers.allOf import java.lang.Thread.sleep -import java.util.concurrent.TimeoutException object ViewActions { - /** - * Performs click on view with very light constraints. Use only if there is no other way - */ - fun callOnClickAction(): ViewAction { - return object : ViewAction { - - override fun getConstraints(): Matcher = allOf(isClickable(), isDisplayed()) - - override fun getDescription() = "Call view onClick directly" - - override fun perform(uiController: UiController, view: View) { - view.callOnClick() - } - } - } - /** * Performs click ignoring 90% visible area constraint */ @@ -64,98 +34,8 @@ object ViewActions { } } - /** - * Performs an action on a child view. - */ - fun actionOnChild(@IdRes id: Int, action: ViewAction): ViewAction { - return object : ViewAction { - - override fun getConstraints(): Matcher = allOf(isDisplayedForClicking(), isClickable()) - - override fun getDescription() = "Performs '$action' on a child view with id='$id'" - - override fun perform(uiController: UiController, view: View) { - val child = view.findViewById(id) - ?: throw PerformException.Builder() - .withActionDescription(this.description) - .withViewDescription(HumanReadables.describe(view)) - .withCause(RuntimeException("View with id='$id' not found in '$view'")) - .build() - action.perform(uiController, child) - } - } - } - - fun clickAtRight(): ViewAction = ViewActions.actionWithAssertions( - GeneralClickAction( - Tap.SINGLE, - GeneralLocation.CENTER_RIGHT, - Press.FINGER, - InputDevice.SOURCE_UNKNOWN, - MotionEvent.BUTTON_PRIMARY - ) - ) - const val WAITING_TIMEOUT = 15_000L const val WAITING_TIMEOUT_PER_TRY = 100L - const val MAIN_THREAD_LOOP_TIME_MS = 50L - - /** - * Wait for view is completely displayed and perform action - */ - fun waitForCompletelyDisplayedAndPerformAction( - targetAction: ViewAction? = null, - timeoutInMillis: Long = WAITING_TIMEOUT, - ) = waitForViewConditionAndPerformAction( - description = "Waits view to become completely displayed.", - timeoutInMillis = timeoutInMillis, - condition = { view -> isCompletelyDisplayed().matches(view) }, - targetAction = targetAction, - ) - - inline fun waitForViewConditionAndPerformAction( - description: String, - targetAction: ViewAction? = null, - timeoutInMillis: Long = WAITING_TIMEOUT, - condition: Matcher, - ) = waitForViewConditionAndPerformAction(description, targetAction, timeoutInMillis, - { view: ViewType -> condition.matches(view) } - ) - - inline fun waitForViewConditionAndPerformAction( - description: String, - targetAction: ViewAction? = null, - timeoutInMillis: Long = WAITING_TIMEOUT, - crossinline condition: (view: ViewType) -> Boolean, - ): ViewAction { - return object : ViewAction { - - override fun getConstraints(): Matcher = isAssignableFrom(ViewType::class.java) - - override fun getDescription() = description - - override fun perform(uiController: UiController, view: View) { - uiController.loopMainThreadUntilIdle() - val startTime = System.currentTimeMillis() - val endTime = startTime + timeoutInMillis - - do { - if (condition(view as ViewType)) { - targetAction?.perform(uiController, view) - return - } - - uiController.loopMainThreadForAtLeast(MAIN_THREAD_LOOP_TIME_MS) - } while (System.currentTimeMillis() < endTime) - - throw PerformException.Builder() - .withActionDescription(this.description) - .withViewDescription(HumanReadables.describe(view)) - .withCause(TimeoutException()) - .build() - } - } - } fun waitForView( viewMatcher: Matcher, diff --git a/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewAssertions.kt b/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewAssertions.kt index b50572511..067fb2144 100644 --- a/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewAssertions.kt +++ b/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewAssertions.kt @@ -1,41 +1,15 @@ package com.yandex.div.view -import android.view.View -import androidx.test.espresso.ViewAssertion import androidx.test.espresso.ViewInteraction import androidx.test.espresso.assertion.ViewAssertions.matches -import androidx.test.espresso.util.HumanReadables import com.yandex.div.view.ViewMatchers.positionMatch import com.yandex.test.util.Report.step -import org.hamcrest.MatcherAssert.assertThat /** * Provides assertions for all types of views. * */ object ViewAssertions { - fun doesNotExistOrGone(): ViewAssertion { - return ViewAssertion { view, _ -> - view?.let { - assertThat( - "View is visible or exists: ${HumanReadables.describe(view)}", - view.visibility == View.GONE || view.visibility == View.INVISIBLE - ) - } - } - } - - fun doesExistAndVisible(): ViewAssertion { - return ViewAssertion { view, ex -> - view?.let { - assertThat( - "View is invisible: ${HumanReadables.describe(view)}", - view.visibility == View.VISIBLE - ) - } ?: throw ViewDoesNotExistsException("View does not exist: ${ex.viewMatcherDescription}") - } - } - fun hasChangedPosition(view: ViewInteraction, lastPosition: FloatArray): Unit = step("Assert view has changed position") { checkPosition(shouldMatch = false, view, lastPosition) @@ -52,5 +26,3 @@ object ViewAssertions { lastPosition: FloatArray ) = view.check(matches(positionMatch(shouldMatch, lastPosition))) } - -class ViewDoesNotExistsException(message: String) : RuntimeException(message) diff --git a/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewInteraction.kt b/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewInteraction.kt index 8e866b800..4a09020d0 100644 --- a/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewInteraction.kt +++ b/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/ViewInteraction.kt @@ -1,37 +1,17 @@ package com.yandex.div.view -import android.view.KeyEvent -import android.view.View import androidx.recyclerview.widget.RecyclerView.ViewHolder import androidx.test.espresso.NoMatchingViewException -import androidx.test.espresso.UiController -import androidx.test.espresso.ViewAction import androidx.test.espresso.ViewInteraction -import androidx.test.espresso.action.GeneralLocation -import androidx.test.espresso.action.GeneralSwipeAction -import androidx.test.espresso.action.Press -import androidx.test.espresso.action.Swipe import androidx.test.espresso.action.ViewActions -import androidx.test.espresso.action.ViewActions.typeText -import androidx.test.espresso.assertion.PositionAssertions import androidx.test.espresso.assertion.ViewAssertions.doesNotExist import androidx.test.espresso.assertion.ViewAssertions.matches -import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition import androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition import androidx.test.espresso.matcher.ViewMatchers -import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed -import com.yandex.div.view.ViewActions.callOnClickAction import com.yandex.div.view.ViewActions.clickOnPartlyVisibleView -import com.yandex.div.view.ViewActions.waitForCompletelyDisplayedAndPerformAction -import com.yandex.div.view.ViewAssertions.doesExistAndVisible -import com.yandex.div.view.ViewAssertions.doesNotExistOrGone import com.yandex.div.view.actions.ExtendedScrollTo -import junit.framework.AssertionFailedError -import org.hamcrest.Matcher fun ViewInteraction.checkIsDisplayed() = check(matches(ViewMatchers.isDisplayed())) -fun ViewInteraction.checkIsChecked() = check(matches(ViewMatchers.isChecked())) -fun ViewInteraction.checkIsNotChecked() = check(matches(ViewMatchers.isNotChecked())) fun ViewInteraction.whenDisplayed(): ViewInteraction? { return try { @@ -45,42 +25,8 @@ fun ViewInteraction.isDisplayed(): Boolean { return whenDisplayed() != null } -fun ViewInteraction.whenChecked(): ViewInteraction? { - return try { - checkIsChecked() - } catch (e: AssertionFailedError) { - null - } -} - -fun ViewInteraction.whenMatches(matcher: Matcher): ViewInteraction? { - return try { - check(matches(matcher)) - } catch (e: AssertionFailedError) { - null - } -} - -fun ViewInteraction.isMatching(matcher: Matcher): Boolean { - return whenMatches(matcher) != null -} - -fun ViewInteraction.whenNotChecked(): ViewInteraction? { - return try { - checkIsNotChecked() - } catch (e: AssertionFailedError) { - null - } -} - fun ViewInteraction.checkNotExist() = check(doesNotExist()) -fun ViewInteraction.checkIsAbove(matcher: Matcher) = check( - PositionAssertions.isCompletelyAbove( - matcher - ) -) - fun ViewInteraction.click() = perform(clickOnPartlyVisibleView()) fun ViewInteraction.tap() = perform(ViewActions.click()) @@ -89,133 +35,6 @@ fun ViewInteraction.scrollTo() = perform(ExtendedScrollTo()) fun ViewInteraction.scrollTo(position: Int) = perform(scrollToPosition(position)) -fun ViewInteraction.callOnClick() = perform(callOnClickAction()) - -fun ViewInteraction.clearText() = perform(ViewActions.clearText()) - -fun ViewInteraction.deleteText() = perform(TextViewActions.clearText()) - -fun ViewInteraction.inputText(text: String) = perform(typeText(text)) - -fun ViewInteraction.replaceText(text: String) = perform(ViewActions.replaceText(text)) - -fun ViewInteraction.clickRecyclerViewItem(index: Int) = - perform(actionOnItemAtPosition(index, ViewActions.click())) - fun ViewInteraction.swipeRight() = perform(ViewActions.swipeRight()) fun ViewInteraction.swipeLeft() = perform(ViewActions.swipeLeft()) fun ViewInteraction.swipeUp() = perform(ViewActions.swipeUp()) -fun ViewInteraction.swipeDown() = perform(ViewActions.swipeDown()) - -fun ViewInteraction.waitForCompletelyDisplayedAndCallOnClick() = - perform(waitForCompletelyDisplayedAndPerformAction(callOnClickAction())) - -fun ViewInteraction.waitForCompletelyDisplayedAndClick() = - perform(waitForCompletelyDisplayedAndPerformAction(ViewActions.click())) - -fun ViewInteraction.waitForCompletelyDisplayedAndLongClick() = - perform(waitForCompletelyDisplayedAndPerformAction(ViewActions.longClick())) - -fun ViewInteraction.pressSpace() = perform(ViewActions.pressKey(KeyEvent.KEYCODE_SPACE)) - -fun ViewInteraction.pressEnter() = perform(ViewActions.pressKey(KeyEvent.KEYCODE_ENTER)) - -fun ViewInteraction.pressBackButton() = perform(ViewActions.pressBack()) - -fun ViewInteraction.swipeLeftCenterToRightCenter() = perform( - waitForCompletelyDisplayedAndPerformAction( - GeneralSwipeAction( - Swipe.FAST, GeneralLocation.CENTER_LEFT, - GeneralLocation.CENTER_RIGHT, Press.FINGER - ) - ) -) - -fun ViewInteraction.swipeRightCenterToLeftCenter() = perform( - waitForCompletelyDisplayedAndPerformAction( - GeneralSwipeAction( - Swipe.FAST, GeneralLocation.CENTER_RIGHT, - GeneralLocation.CENTER_LEFT, Press.FINGER - ) - ) -) - -fun ViewInteraction.swipeTopCenterToBottomCenter() = perform( - waitForCompletelyDisplayedAndPerformAction( - GeneralSwipeAction( - Swipe.FAST, GeneralLocation.TOP_CENTER, - GeneralLocation.BOTTOM_CENTER, Press.FINGER - ) - ) -) - -fun ViewInteraction.swipeFromCenterToBottomCenter(swipeSpeed: Swipe = Swipe.SLOW) = perform( - waitForCompletelyDisplayedAndPerformAction( - GeneralSwipeAction( - swipeSpeed, - GeneralLocation.CENTER, - GeneralLocation.BOTTOM_CENTER, Press.FINGER - ) - ) -) - -fun ViewInteraction.swipeFromCenterToTopCenter(swipeSpeed: Swipe = Swipe.SLOW) = perform( - waitForCompletelyDisplayedAndPerformAction( - GeneralSwipeAction( - swipeSpeed, - GeneralLocation.CENTER, - GeneralLocation.TOP_CENTER, Press.FINGER - ) - ) -) - -fun ViewInteraction.waitForCompletelyDisplayed( - timeoutInMillis: Long? = null -): ViewInteraction { - return if (timeoutInMillis == null) - perform(waitForCompletelyDisplayedAndPerformAction()) - else perform( - waitForCompletelyDisplayedAndPerformAction( - timeoutInMillis = timeoutInMillis - ) - ) -} - -fun ViewInteraction.waitMainThreadBecomeIdle(): ViewInteraction { - return perform(object : ViewAction { - - override fun getDescription(): String = - "Wait while main thread become idle on displayed view" - - override fun getConstraints(): Matcher = ViewMatchers.isDisplayed() - - override fun perform(uiController: UiController, view: View) = - uiController.loopMainThreadUntilIdle() - }) -} - -fun ViewInteraction.checkExistsAndVisible() = check(doesExistAndVisible()) - -fun ViewInteraction.checkExistsAndCompletelyVisible() = check(matches(isCompletelyDisplayed())) - -fun ViewInteraction.checkNotExistsOrGone() = check(doesNotExistOrGone()) - - -fun ViewInteraction.configure(block: (T) -> Unit): ViewInteraction { - return perform(ViewActions.actionWithAssertions(ConfigureViewAction(block))) -} - -private class ConfigureViewAction( - private val block: (T) -> Unit -) : ViewAction { - - override fun getDescription() = "ConfigureViewAction" - - override fun getConstraints(): Matcher = ViewMatchers.isDisplayed() - - @Suppress("UNCHECKED_CAST") - override fun perform(uiController: UiController, view: View) { - val receiver = view as? T ?: return - block(receiver) - } -} diff --git a/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/getThemeColor.kt b/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/getThemeColor.kt deleted file mode 100644 index 528534885..000000000 --- a/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/getThemeColor.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.yandex.div.view - -import android.content.Context -import android.util.TypedValue -import androidx.annotation.AttrRes -import androidx.annotation.ColorInt - -/** - * Returns the color int for the provided theme color attribute. - * - * @throws IllegalArgumentException if the attribute is not set in the current theme. - */ -@ColorInt -fun Context.getThemeColor(@AttrRes attribute: Int): Int { - val typedValue = resolveAttributeOrThrow(attribute) - return typedValue.data -} - -fun Context.getThemeBoolean(@AttrRes attribute: Int): Boolean { - return resolveAttributeOrThrow(attribute).data != 0 -} - -fun Context.getThemeResource(@AttrRes attribute: Int): Int { - return resolveAttributeOrThrow(attribute).resourceId -} - -internal fun Context.resolveAttributeOrThrow(@AttrRes attributeResId: Int): TypedValue { - val typedValue = TypedValue() - - val isAttrResolved = theme.resolveAttribute(attributeResId, typedValue, true) - if (isAttrResolved) { - return typedValue - } - - val errorMessage = ("%1\$s requires a value for the %2\$s attribute to be set in your theme.") - throw java.lang.IllegalArgumentException( - String.format( - errorMessage, - javaClass.canonicalName, - resources.getResourceName(attributeResId), - ) - ) -} diff --git a/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/viewHelpers.kt b/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/viewHelpers.kt deleted file mode 100644 index d10ab7622..000000000 --- a/client/android/divkit-demo-app/src/androidTest/java/com/yandex/div/view/viewHelpers.kt +++ /dev/null @@ -1,271 +0,0 @@ -package com.yandex.div.view - -import android.animation.AnimatorInflater -import android.app.Activity -import android.content.ContextWrapper -import android.graphics.PorterDuff -import android.graphics.PorterDuffColorFilter -import android.os.Build -import android.view.View -import android.view.ViewGroup -import android.view.ViewGroup.MarginLayoutParams -import android.widget.CompoundButton -import android.widget.TextView -import androidx.annotation.AnimatorRes -import androidx.annotation.AttrRes -import androidx.annotation.ColorInt -import androidx.annotation.ColorRes -import androidx.annotation.DimenRes -import androidx.annotation.DrawableRes -import androidx.annotation.Px -import androidx.constraintlayout.widget.ConstraintLayout -import androidx.core.content.res.ResourcesCompat -import androidx.core.view.marginBottom -import androidx.core.view.marginLeft -import androidx.core.view.marginRight -import androidx.core.view.marginTop -import com.yandex.divkit.demo.utils.coroutineScope -import com.yandex.divkit.demo.utils.noGetter -import kotlinx.coroutines.launch - -const val matchParent: Int = ViewGroup.LayoutParams.MATCH_PARENT -const val wrapContent: Int = ViewGroup.LayoutParams.WRAP_CONTENT -const val matchConstraint: Int = ConstraintLayout.LayoutParams.MATCH_CONSTRAINT - -var TextView.textColor: Int - @ColorInt get() = textColors.defaultColor - set(@ColorInt value) = setTextColor(value) - -var TextView.textColorResource: Int - get() = noGetter() - set(colorId) = setTextColor(context.resources.run { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) getColor(colorId, null) else getColor(colorId) - }) - -var TextView.textColorAttr: Int - get() = noGetter() - set(@AttrRes value) = setTextColor(context.getThemeColor(value)) - -var TextView.textColorHint: Int - get() = hintTextColors.defaultColor - set(value) = setHintTextColor(value) - -var TextView.textColorHintResource: Int - get() = noGetter() - set(colorId) = setHintTextColor(context.resources.run { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) getColor(colorId, null) else getColor(colorId) - }) - -var TextView.fontResource: Int - get() = noGetter() - set(fontId) { - typeface = ResourcesCompat.getFont(context, fontId) - } - -var TextView.lineSpacingAdd: Float - get() = lineSpacingExtra - set(value) = setLineSpacing(value, lineSpacingMultiplier) - -var TextView.lineSpacingMult: Float - get() = lineSpacingMultiplier - set(value) = setLineSpacing(lineSpacingExtra, value) - -var TextView.textResource: Int - get() = noGetter() - set(v) = setText(v) - -var TextView.hintResource: Int - get() = noGetter() - set(value) = setHint(value) - -var View.backgroundColor: Int - get() = noGetter() - set(@ColorInt value) = setBackgroundColor(value) - -var View.backgroundColorResource: Int - get() = noGetter() - set(@ColorRes value) = setBackgroundColor(ResourcesCompat.getColor(resources, value, null)) - -var View.backgroundColorAttr: Int - get() = noGetter() - set(@AttrRes value) = setBackgroundColor(context.getThemeColor(value)) - -var View.backgroundResource: Int - get() = noGetter() - set(@DrawableRes value) = setBackgroundResource(value) - - -var View.backgroundTintColor: Int - get() = noGetter() - set(@ColorInt value) { - background?.colorFilter = PorterDuffColorFilter(value, PorterDuff.Mode.SRC_ATOP) - } - -var View.backgroundTintColorResource: Int - get() = noGetter() - set(@ColorRes value) { - backgroundTintColor = ResourcesCompat.getColor(resources, value, null) - } - -fun View.onClick(value: suspend () -> Unit) { - setOnClickListener { - activity.coroutineScope.launch { value() } - } -} - -fun View.clearClickListener() = setOnClickListener(null) - -fun View.onLongClick(value: suspend () -> Unit) { - setOnLongClickListener { - activity.coroutineScope.launch { value() } - true - } -} - -var View.leftPadding: Int - get() = paddingLeft - set(value) = setPadding(value, paddingTop, paddingRight, paddingBottom) - -var View.rightPadding: Int - get() = paddingRight - set(value) = setPadding(paddingLeft, paddingTop, value, paddingBottom) - -var View.topPadding: Int - get() = paddingTop - set(value) = setPadding(paddingLeft, value, paddingRight, paddingBottom) - -var View.bottomPadding: Int - get() = paddingBottom - set(value) = setPadding(paddingLeft, paddingTop, paddingRight, value) - -var View.padding: Int - get() = noGetter() - set(value) = setPadding(value, value, value, value) - -var View.verticalPadding: Int - get() = noGetter() - set(value) = setPadding(paddingLeft, value, paddingRight, value) - -var View.horizontalPadding: Int - get() = noGetter() - set(value) = setPadding(value, paddingTop, value, paddingBottom) - -var View.stateListAnimatorResource: Int - get() = noGetter() - set(@AnimatorRes value) { - stateListAnimator = AnimatorInflater.loadStateListAnimator(context, value) - } - -var View.topMargin: Int - get() = noGetter() - set(value) { - withMarginLayoutParams { - topMargin = value - } - } - -var View.leftMargin: Int - get() = noGetter() - set(value) { - withMarginLayoutParams { - leftMargin = value - } - } - -var View.bottomMargin: Int - get() = noGetter() - set(value) { - withMarginLayoutParams { - bottomMargin = value - } - } - -var View.rightMargin: Int - get() = noGetter() - set(value) { - withMarginLayoutParams { - rightMargin = value - } - } - -var View.topMarginRes: Int - get() = noGetter() - set(@DimenRes value) { - withMarginLayoutParams { - topMargin = context.resources.getDimensionPixelSize(value) - } - } - -var View.leftMarginRes: Int - get() = noGetter() - set(@DimenRes value) { - withMarginLayoutParams { - leftMargin = context.resources.getDimensionPixelSize(value) - } - } - -var View.bottomMarginRes: Int - get() = noGetter() - set(@DimenRes value) { - withMarginLayoutParams { - bottomMargin = context.resources.getDimensionPixelSize(value) - } - } - -var View.rightMarginRes: Int - get() = noGetter() - set(@DimenRes value) { - withMarginLayoutParams { - rightMargin = context.resources.getDimensionPixelSize(value) - } - } - -fun View.updateMargins( - @Px left: Int = marginLeft, - @Px top: Int = marginTop, - @Px right: Int = marginRight, - @Px bottom: Int = marginBottom -) { - if (marginLeft == left && marginTop == top && marginBottom == bottom && marginRight == right) { - return - } - withMarginLayoutParams { - topMargin = top - bottomMargin = bottom - leftMargin = left - rightMargin = right - } -} - -inline fun View.withMarginLayoutParams(block: MarginLayoutParams.() -> Unit) = withLayoutParams(block) - -inline fun View.withLayoutParams(block: T.() -> Unit) { - (layoutParams as? T)?.let { lp -> - lp.block() - layoutParams = lp - } -} - -inline fun View.onLayoutChange(crossinline onLayoutChange: () -> Unit) = - addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ -> onLayoutChange() } - -inline fun CompoundButton.onCheckedChange(crossinline onCheckedChange: (Boolean) -> Unit) = - setOnCheckedChangeListener { _, isChecked -> onCheckedChange(isChecked) } - -val View.activity: Activity - get() { - when (val context = context) { - is Activity -> return context - is ContextWrapper -> { - var contextWrapper = context - while (contextWrapper is ContextWrapper) { - if (contextWrapper is Activity) { - return contextWrapper - } - contextWrapper = contextWrapper.baseContext - } - error("Unknown view context $contextWrapper") - } - else -> error("Unknown view context $context") - } - } diff --git a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/Container.kt b/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/Container.kt index cc1205052..1e535af58 100644 --- a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/Container.kt +++ b/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/Container.kt @@ -2,7 +2,6 @@ package com.yandex.divkit.demo import android.annotation.SuppressLint import android.content.Context -import android.os.Build import com.facebook.stetho.okhttp3.StethoInterceptor import com.neovisionaries.ws.client.WebSocketFactory import com.yandex.div.coil.CoilDivImageLoader @@ -74,11 +73,9 @@ internal object Container { .setSSLContext(NaiveSSLContext.getInstance("TLS")) .setConnectionTimeout(TimeUnit.SECONDS.toMillis(15).toInt()) .apply { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - context.connectivityManager.defaultProxy?.let { proxyInfo -> - proxySettings.host = proxyInfo.host - proxySettings.port = proxyInfo.port - } + context.connectivityManager.defaultProxy?.let { proxyInfo -> + proxySettings.host = proxyInfo.host + proxySettings.port = proxyInfo.port } } } diff --git a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/div/Div2Activity.kt b/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/div/Div2Activity.kt index 62ddea9ea..ddf96f8fe 100644 --- a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/div/Div2Activity.kt +++ b/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/div/Div2Activity.kt @@ -9,7 +9,6 @@ import android.content.pm.PackageManager import android.content.res.Configuration import android.graphics.Path import android.net.Uri -import android.os.Build import android.os.Bundle import android.view.View import android.view.ViewGroup @@ -26,7 +25,6 @@ import com.yandex.div.core.DivDataChangeListener import com.yandex.div.core.DivViewFacade import com.yandex.div.core.state.DivStateChangeListener import com.yandex.div.core.state.DivStateTransition -import com.yandex.div.core.util.SafeAlertDialogBuilder import com.yandex.div.core.view2.Div2View import com.yandex.div.data.Variable import com.yandex.div.font.YandexSansDisplayDivTypefaceProvider @@ -280,13 +278,7 @@ class Div2Activity : AppCompatActivity() { private fun (() -> Unit).invokeWithPermissions(vararg permissions: String) = when { checkPermissions(permissions) -> invoke() - Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> - requestPermissions(permissions, OPEN_FILE_ACTIVITY_REQUEST_CODE) - else -> SafeAlertDialogBuilder(this@Div2Activity) - .setTitle("Unable to add new template from storage: no permissions") - .setPositiveButton("Ok") { dialog, id -> - dialog.cancel() - } + else -> requestPermissions(permissions, OPEN_FILE_ACTIVITY_REQUEST_CODE) } private fun checkPermissions(permissions: Array) = diff --git a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/div/DivActivity.kt b/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/div/DivActivity.kt index 98e4aa3a5..b8bb1a3a9 100644 --- a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/div/DivActivity.kt +++ b/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/div/DivActivity.kt @@ -5,7 +5,6 @@ import android.content.Intent import android.content.pm.PackageManager import android.content.res.Configuration import android.graphics.Color -import android.os.Build import android.os.Bundle import android.text.TextUtils import android.view.View @@ -175,12 +174,8 @@ open class DivActivity : AppCompatActivity() { private fun (()->Unit).invokeWithPermissions(vararg permissions: String) = when { - checkPermissions(permissions) -> - invoke() - Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> - requestPermissions(permissions, REQUEST_CODE) - else -> - noPermissions() + checkPermissions(permissions) -> invoke() + else -> requestPermissions(permissions, REQUEST_CODE) } private fun checkPermissions(permissions: Array) = diff --git a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/screenshot/DivAssetReader.kt b/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/screenshot/DivAssetReader.kt index dbcc8e65a..679e7e006 100644 --- a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/screenshot/DivAssetReader.kt +++ b/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/screenshot/DivAssetReader.kt @@ -1,7 +1,6 @@ package com.yandex.divkit.demo.screenshot import android.content.Context -import android.os.Build import com.yandex.div.internal.util.IOUtils import org.json.JSONObject @@ -9,21 +8,6 @@ class DivAssetReader(private val context: Context) { fun read(filename: String): JSONObject { val data = IOUtils.toString(context.assets.open(filename)) - .replaceUnsupportedUnicodeSymbols() return JSONObject(data) } - - private fun String.replaceUnsupportedUnicodeSymbols(): String { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) return this - var result = this - UNSUPPORTED_UNICODE_PRE_M.forEachIndexed { index, unsupportedString -> - result = result.replace(unsupportedString, UNSUPPORTED_UNICODE_REPLACEMENTS[index]) - } - return result - } - - companion object { - private val UNSUPPORTED_UNICODE_PRE_M = arrayOf("⌜", "⌝", "⌞", "⌄", "⌟") - private val UNSUPPORTED_UNICODE_REPLACEMENTS = arrayOf("tl", "tr", "bl", "b", "br") - } } diff --git a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/uri/CustomTabHelper.kt b/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/uri/CustomTabHelper.kt index 1e27bee42..5da11f1b4 100644 --- a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/uri/CustomTabHelper.kt +++ b/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/uri/CustomTabHelper.kt @@ -4,7 +4,6 @@ import android.content.ActivityNotFoundException import android.content.ComponentName import android.content.Context import android.net.Uri -import android.os.Build import android.os.Parcelable import androidx.annotation.ColorInt import androidx.browser.customtabs.CustomTabsClient @@ -32,11 +31,7 @@ class CustomTabHelper(private val context: Context) { } val intentBuilder = CustomTabsIntent.Builder(customTabSession) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - intentBuilder.setToolbarColor(context.resources.getColor(R.color.colorPrimary, null)) - } else { - intentBuilder.setToolbarColor(context.resources.getColor(R.color.colorPrimary)) - } + intentBuilder.setToolbarColor(context.resources.getColor(R.color.colorPrimary, null)) if (colors != null) { colors.toolbarColor?.let { intentBuilder.setToolbarColor(it) } diff --git a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/DivkitDemoPermissionHelper.kt b/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/DivkitDemoPermissionHelper.kt index d069e91a5..edbc0534d 100644 --- a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/DivkitDemoPermissionHelper.kt +++ b/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/DivkitDemoPermissionHelper.kt @@ -3,7 +3,6 @@ package com.yandex.divkit.demo.utils import android.Manifest import android.app.Activity import android.content.pm.PackageManager -import android.os.Build import android.widget.Toast import androidx.annotation.StringRes import androidx.core.app.ActivityCompat @@ -12,49 +11,24 @@ import androidx.core.content.ContextCompat /** * Encapsulates permissions requesting logic */ -class DivkitDemoPermissionHelper(private val activity: Activity) { +object DivkitDemoPermissionHelper { - companion object { - const val LOCATION_PERMISSION_REQUEST_CODE = 101 - private const val READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE = 102 + private const val READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE = 102 + private const val READ_EXTERNAL_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE - const val ACCESS_COARSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION - const val ACCESS_FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION - private const val READ_EXTERNAL_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE + fun requestReadExternalStoragePermission(activity: Activity, @StringRes rationale: Int) { + if (ContextCompat.checkSelfPermission(activity, READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + return + } - fun requestReadExternalStoragePermission(activity: Activity, @StringRes rationale: Int) { - if (ContextCompat.checkSelfPermission(activity, READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { - return - } - - if (ActivityCompat.shouldShowRequestPermissionRationale(activity, READ_EXTERNAL_STORAGE)) { - Toast.makeText(activity, rationale, Toast.LENGTH_LONG).show() - } else { - ActivityCompat.requestPermissions(activity, arrayOf(READ_EXTERNAL_STORAGE), READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE) - } + if (ActivityCompat.shouldShowRequestPermissionRationale(activity, READ_EXTERNAL_STORAGE)) { + Toast.makeText(activity, rationale, Toast.LENGTH_LONG).show() + } else { + ActivityCompat.requestPermissions( + activity, + arrayOf(READ_EXTERNAL_STORAGE), + READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE + ) } } - - private var locationPermissionGrantedCallback: Runnable? = null - - fun requestLocationPermission(callback: Runnable) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - activity.requestPermissions(arrayOf(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE) - locationPermissionGrantedCallback = callback - } - } - - fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - when (requestCode) { - LOCATION_PERMISSION_REQUEST_CODE -> { - if (isGranted(ACCESS_COARSE_LOCATION, permissions, grantResults) || isGranted(ACCESS_FINE_LOCATION, permissions, grantResults)) { - locationPermissionGrantedCallback?.run() - locationPermissionGrantedCallback = null - } - } - } - } - - private fun isGranted(permission: String, permissions: Array, grantResults: IntArray) = - permissions.contains(permission) && grantResults[permissions.indexOf(permission)] == PackageManager.PERMISSION_GRANTED } diff --git a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/JsonAssetReader.kt b/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/JsonAssetReader.kt deleted file mode 100644 index 6bfe9870d..000000000 --- a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/utils/JsonAssetReader.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.yandex.divkit.demo.utils - -import android.content.Context -import androidx.annotation.WorkerThread -import org.json.JSONException -import org.json.JSONObject -import java.io.IOException - -internal class JsonAssetReader( - private val context: Context -) { - - @WorkerThread - @Throws(IOException::class) - fun readBytes(filename: String): ByteArray { - val stream = context.assets.open(filename) - stream.use { - return stream.readBytes() - } - } - - @WorkerThread - @Throws(IOException::class) - fun readText(filename: String): String { - return readBytes(filename).toString(charset = Charsets.UTF_8) - } - - @WorkerThread - @Throws(IOException::class, JSONException::class) - fun readJson(filename: String): JSONObject { - return JSONObject(readText(filename)) - } -} diff --git a/client/android/divkit-demo-app/src/screenshotTest/screenshots/API28_XHDPI_720x1600/viewRender/com.yandex.div.DivComposeScreenshotTest/div-container/alpha-and-background.png b/client/android/divkit-demo-app/src/screenshotTest/screenshots/API28_XHDPI_720x1600/viewRender/com.yandex.div.DivComposeScreenshotTest/div-container/alpha-and-background.png index 4bdb74d88..f2406614a 100644 Binary files a/client/android/divkit-demo-app/src/screenshotTest/screenshots/API28_XHDPI_720x1600/viewRender/com.yandex.div.DivComposeScreenshotTest/div-container/alpha-and-background.png and b/client/android/divkit-demo-app/src/screenshotTest/screenshots/API28_XHDPI_720x1600/viewRender/com.yandex.div.DivComposeScreenshotTest/div-container/alpha-and-background.png differ diff --git a/client/android/divkit-demo-app/src/screenshotTest/screenshots/API28_XHDPI_720x1600/viewRender/com.yandex.div.DivComposeScreenshotTest/div-gallery/horizontal-gallery-items-not-fit.png b/client/android/divkit-demo-app/src/screenshotTest/screenshots/API28_XHDPI_720x1600/viewRender/com.yandex.div.DivComposeScreenshotTest/div-gallery/horizontal-gallery-items-not-fit.png index bb053234e..104b4217b 100644 Binary files a/client/android/divkit-demo-app/src/screenshotTest/screenshots/API28_XHDPI_720x1600/viewRender/com.yandex.div.DivComposeScreenshotTest/div-gallery/horizontal-gallery-items-not-fit.png and b/client/android/divkit-demo-app/src/screenshotTest/screenshots/API28_XHDPI_720x1600/viewRender/com.yandex.div.DivComposeScreenshotTest/div-gallery/horizontal-gallery-items-not-fit.png differ diff --git a/client/android/divkit-demo-app/src/screenshotTest/screenshots/API28_XHDPI_720x1600/viewRender/com.yandex.div.DivComposeScreenshotTest/div-gallery/vertical-gallery-items-not-fit.png b/client/android/divkit-demo-app/src/screenshotTest/screenshots/API28_XHDPI_720x1600/viewRender/com.yandex.div.DivComposeScreenshotTest/div-gallery/vertical-gallery-items-not-fit.png index 8d4d4482e..1c9a6e879 100644 Binary files a/client/android/divkit-demo-app/src/screenshotTest/screenshots/API28_XHDPI_720x1600/viewRender/com.yandex.div.DivComposeScreenshotTest/div-gallery/vertical-gallery-items-not-fit.png and b/client/android/divkit-demo-app/src/screenshotTest/screenshots/API28_XHDPI_720x1600/viewRender/com.yandex.div.DivComposeScreenshotTest/div-gallery/vertical-gallery-items-not-fit.png differ diff --git a/client/android/divkit-demo-app/src/screenshotTest/screenshots/API28_XHDPI_720x1600/viewRender/com.yandex.div.DivComposeScreenshotTest/div-image/custom-alpha.png b/client/android/divkit-demo-app/src/screenshotTest/screenshots/API28_XHDPI_720x1600/viewRender/com.yandex.div.DivComposeScreenshotTest/div-image/custom-alpha.png index be98940b5..3421cec43 100644 Binary files a/client/android/divkit-demo-app/src/screenshotTest/screenshots/API28_XHDPI_720x1600/viewRender/com.yandex.div.DivComposeScreenshotTest/div-image/custom-alpha.png and b/client/android/divkit-demo-app/src/screenshotTest/screenshots/API28_XHDPI_720x1600/viewRender/com.yandex.div.DivComposeScreenshotTest/div-image/custom-alpha.png differ diff --git a/client/android/gradle/libs.versions.toml b/client/android/gradle/libs.versions.toml index d501e21d4..e8156003e 100644 --- a/client/android/gradle/libs.versions.toml +++ b/client/android/gradle/libs.versions.toml @@ -41,7 +41,7 @@ androidx-annotation = "1.9.1" androidx-appcompat = "1.6.1" androidx-browser = "1.8.0" androidx-collection = "1.5.0" -androidx-compose-bom = "2024.04.00" +androidx-compose-bom = "2026.03.00" androidx-constraint = "2.2.1" androidx-core = "1.16.0" androidx-espresso = "3.7.0" diff --git a/client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivBackgroundUtils.kt b/client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivBackgroundUtils.kt new file mode 100644 index 000000000..61aa0f18e --- /dev/null +++ b/client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivBackgroundUtils.kt @@ -0,0 +1,13 @@ +package com.yandex.div.test.data + +import com.yandex.div.evaluable.types.Color +import com.yandex.div2.DivBackground +import com.yandex.div2.DivSolidBackground + +fun solidBackground(color: Color): DivBackground { + return DivBackground.Solid( + value = DivSolidBackground( + color = constant(color.value) + ) + ) +} diff --git a/client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivContainerUtils.kt b/client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivContainerUtils.kt index 6924c547e..3e613b144 100644 --- a/client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivContainerUtils.kt +++ b/client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivContainerUtils.kt @@ -1,16 +1,24 @@ package com.yandex.div.test.data import com.yandex.div2.Div +import com.yandex.div2.DivBackground import com.yandex.div2.DivContainer +import com.yandex.div2.DivEdgeInsets import com.yandex.div2.DivVariable fun container( + backgrounds: List? = null, items: List
= emptyList(), + margins: DivEdgeInsets? = null, + paddings: DivEdgeInsets? = null, variables: List? = null ): Div { return Div.Container( value = DivContainer( + background = backgrounds, items = items, + margins = margins, + paddings = paddings, variables = variables ) ) diff --git a/client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivTextUtils.kt b/client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivTextUtils.kt index 765147a8a..45e2e47d8 100644 --- a/client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivTextUtils.kt +++ b/client/android/test-utils/src/main/kotlin/com/yandex/div/test/data/DivTextUtils.kt @@ -1,5 +1,6 @@ package com.yandex.div.test.data +import com.yandex.div.evaluable.types.Color import com.yandex.div.json.expressions.Expression import com.yandex.div2.Div import com.yandex.div2.DivAction @@ -10,10 +11,30 @@ import com.yandex.div2.DivVariable import com.yandex.div2.DivVisibilityAction fun text( - action: DivAction? = null, disappearActions: List? = null, id: String? = null, + text: String, + triggers: List? = null, + variables: List? = null, + visibilityActions: List? = null +): Div { + return text( + disappearActions = disappearActions, + id = id, + text = constant(text), + triggers = triggers, + variables = variables, + visibilityActions = visibilityActions + ) +} + +fun text( + action: DivAction? = null, + disappearActions: List? = null, + fontSize: Long = 12, + id: String? = null, text: Expression, + textColor: Color? = null, triggers: List? = null, variables: List? = null, visibilityActions: List? = null @@ -22,8 +43,10 @@ fun text( value = DivText( action = action, disappearActions = disappearActions, + fontSize = constant(fontSize), id = id, text = text, + textColor = textColor?.let { constant(it.value) } ?: constant(0xFF000000.toInt()), variables = variables, variableTriggers = triggers, visibilityActions = visibilityActions