Skip to content

Commit

Permalink
Replace ProgressSpec with Progress Primitive Component
Browse files Browse the repository at this point in the history
Summary:
As per title - this diff replaces `ProgressSpec` component with a Progress Primitive Component.

In this change, we're:
1. Moving `Progress` Primitive Component from Litho sample app to litho widget module.
2. Renaming `Progress` Primitive Component to `ExperimentalProgress`.
3. Renaming `ProgressSpec` to `ProgressComponentSpec`
4. Introducing `ProgressSpec` LayoutSpec which returns either `ProgressComponentSpec` or `ExperimentalProgress` depending on MC value.

Reviewed By: apowolny

Differential Revision: D65139347

fbshipit-source-id: 5632801d3b62c7fa98cc8b611d4b6732fce1388c
  • Loading branch information
zielinskimz authored and facebook-github-bot committed Oct 30, 2024
1 parent 748de68 commit d4e82f9
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,11 @@ internal constructor(
*/
@JvmField var usePrimitiveImage: Boolean = false

/**
* This flag is used to enable using PrimitiveComponent implementation of a Progress component.
*/
@JvmField var usePrimitiveProgress: Boolean = false

/** This config will enable logging of interactable components with 0 alpha */
@JvmField var isZeroAlphaLoggingEnabled: Boolean = false

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ public void testUnsetSize() {
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));

assertThat(view.getMeasuredWidth()).isEqualTo(ProgressSpec.DEFAULT_SIZE);
assertThat(view.getMeasuredHeight()).isEqualTo(ProgressSpec.DEFAULT_SIZE);
assertThat(view.getMeasuredWidth()).isEqualTo(ProgressComponentSpec.DEFAULT_SIZE);
assertThat(view.getMeasuredHeight()).isEqualTo(ProgressComponentSpec.DEFAULT_SIZE);
}

private LithoView getMountedView() {
Progress.Builder progress = Progress.create(mContext);
ProgressComponent.Builder progress = ProgressComponent.create(mContext);

return ComponentTestHelper.mountComponent(progress);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,17 @@
* limitations under the License.
*/

package com.facebook.samples.litho.kotlin.primitives.widgets
package com.facebook.litho.widget

import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import androidx.core.graphics.BlendModeColorFilterCompat
import androidx.core.graphics.BlendModeCompat
import com.facebook.litho.LithoPrimitive
import com.facebook.litho.PrimitiveComponent
import com.facebook.litho.PrimitiveComponentScope
import com.facebook.litho.Style
import com.facebook.litho.widget.ProgressView
import com.facebook.litho.annotations.ExperimentalLithoApi
import com.facebook.rendercore.Size
import com.facebook.rendercore.SizeConstraints
import com.facebook.rendercore.primitives.LayoutBehavior
Expand All @@ -38,33 +39,35 @@ import com.facebook.rendercore.utils.withEqualDimensions
* @param indeterminateDrawable Drawable to be shown to show progress.
* @param color Tint color for the drawable.
*/
class Progress(
@ExperimentalLithoApi
class ExperimentalProgress(
private val color: Int = Color.TRANSPARENT,
private val indeterminateDrawable: Drawable? = null,
private val style: Style? = null
) : PrimitiveComponent() {

@Suppress("DEPRECATION")
override fun PrimitiveComponentScope.render(): LithoPrimitive {
return LithoPrimitive(
layoutBehavior = ProgressLayoutBehavior,
mountBehavior =
MountBehavior(ViewAllocator { context -> ProgressView(context) }) {
bind(indeterminateDrawable, color) { content ->
val defaultIndeterminateDrawable = content.indeterminateDrawable

indeterminateDrawable?.let { content.indeterminateDrawable = indeterminateDrawable }
content.indeterminateDrawable?.let {
if (color != Color.TRANSPARENT) {
content.indeterminateDrawable
.mutate()
.setColorFilter(color, PorterDuff.Mode.MULTIPLY)
content.indeterminateDrawable.mutate().colorFilter =
BlendModeColorFilterCompat.createBlendModeColorFilterCompat(
color, BlendModeCompat.MODULATE)
}
}
onUnbind {
// restore the color first, since it acts on the indeterminateDrawable
if (color != Color.TRANSPARENT && content.indeterminateDrawable != null) {
content.indeterminateDrawable.mutate().clearColorFilter()
}

content.indeterminateDrawable = defaultIndeterminateDrawable
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
* @prop color Tint color for the drawable.
*/
@MountSpec(isPureRender = true)
class ProgressSpec {
class ProgressComponentSpec {

static final int DEFAULT_SIZE = 50;

Expand All @@ -65,7 +65,7 @@ static void onLoadStyle(ComponentContext c, Output<Drawable> indeterminateDrawab
@OnPrepare
static void onPrepare(
ComponentContext c,
@Prop(optional = true, resType = ResType.DRAWABLE) Drawable indeterminateDrawable,
@Prop(optional = true, resType = ResType.DRAWABLE) @Nullable Drawable indeterminateDrawable,
Output<Drawable> resolvedIndeterminateDrawable) {
if (indeterminateDrawable != null) {
resolvedIndeterminateDrawable.set(indeterminateDrawable);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.facebook.litho.widget

import android.graphics.Color
import android.graphics.drawable.Drawable
import com.facebook.litho.Component
import com.facebook.litho.ComponentContext
import com.facebook.litho.annotations.ExcuseMySpec
import com.facebook.litho.annotations.ExperimentalLithoApi
import com.facebook.litho.annotations.LayoutSpec
import com.facebook.litho.annotations.OnCreateLayout
import com.facebook.litho.annotations.Prop
import com.facebook.litho.annotations.PropDefault
import com.facebook.litho.annotations.Reason
import com.facebook.litho.annotations.ResType
import com.facebook.litho.config.ComponentsConfiguration

/**
* Renders an infinitely spinning progress bar.
*
* @uidocs
* @prop indeterminateDrawable Drawable to be shown to show progress.
* @prop color Tint color for the drawable.
*/
@ExcuseMySpec(reason = Reason.J2K_CONVERSION)
@LayoutSpec
object ProgressSpec {

@PropDefault val color: Int = Color.TRANSPARENT

@OptIn(ExperimentalLithoApi::class)
@OnCreateLayout
fun onCreateLayout(
c: ComponentContext,
@Prop(optional = true, resType = ResType.COLOR) color: Int,
@Prop(optional = true, resType = ResType.DRAWABLE) indeterminateDrawable: Drawable?,
): Component {
return if (ComponentsConfiguration.usePrimitiveProgress) {
ExperimentalProgress(
color = color,
indeterminateDrawable = indeterminateDrawable,
)
} else {
ProgressComponent.create(c).color(color).indeterminateDrawable(indeterminateDrawable).build()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import com.facebook.litho.kotlin.widget.Text
import com.facebook.litho.view.background
import com.facebook.litho.view.backgroundColor
import com.facebook.litho.widget.ExperimentalImage
import com.facebook.litho.widget.ExperimentalProgress
import com.facebook.rendercore.dp
import com.facebook.rendercore.drawableRes
import com.facebook.samples.litho.R.drawable.ic_launcher
Expand Down Expand Up @@ -59,7 +60,7 @@ class PrimitiveWidgetsExampleComponent : KComponent() {
ExperimentalImage(
drawable = drawableRes(ic_launcher), style = Style.width(100.dp).height(100.dp)))
child(Text("Progress"))
child(Progress(style = Style.width(100.dp).height(100.dp)))
child(ExperimentalProgress(style = Style.width(100.dp).height(100.dp)))
child(Text("Horizontal Scroll"))
child(HorizontalScroll { Row { getComponents(this) } })
child(Text("Vertical Scroll"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ package com.facebook.samples.litho.kotlin.primitives.widgets
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import com.facebook.litho.Style
import com.facebook.litho.annotations.ExperimentalLithoApi
import com.facebook.litho.core.height
import com.facebook.litho.core.width
import com.facebook.litho.testing.LithoTestRule
import com.facebook.litho.testing.assertj.LithoAssertions.assertThat
import com.facebook.litho.testing.testrunner.LithoTestRunner
import com.facebook.litho.widget.ExperimentalProgress
import com.facebook.litho.widget.ProgressView
import com.facebook.rendercore.px
import junit.framework.Assert.assertNotNull
Expand All @@ -33,6 +35,7 @@ import org.junit.Test
import org.junit.runner.RunWith

/** Tests for [ProgressComponent] */
@OptIn(ExperimentalLithoApi::class)
@RunWith(LithoTestRunner::class)
class ProgressTest {

Expand All @@ -41,10 +44,10 @@ class ProgressTest {
@Test
fun `ProgressComponent should render`() {
val testLithoView =
lithoViewRule.render { Progress(style = Style.width(100.px).height(100.px)) }
lithoViewRule.render { ExperimentalProgress(style = Style.width(100.px).height(100.px)) }

// should find an Progress in the tree
assertNotNull(testLithoView.findComponent(Progress::class))
assertNotNull(testLithoView.findComponent(ExperimentalProgress::class))

// should mount an Progress
assertThat(testLithoView.lithoView.mountItemCount).isEqualTo(1)
Expand All @@ -56,8 +59,8 @@ class ProgressTest {

@Test
fun `same instance should be equivalent`() {
val component = Progress()
val component2 = Progress()
val component = ExperimentalProgress()
val component2 = ExperimentalProgress()

assertThat(component).isEquivalentTo(component2)
assertThat(component).isEquivalentTo(component2, true)
Expand All @@ -67,13 +70,15 @@ class ProgressTest {
fun `components with same prop values should be equivalent`() {
val colorDrawable = ColorDrawable(Color.RED)
val color = Color.BLACK
val firstProgressWithColorDrawable = Progress(indeterminateDrawable = colorDrawable)
val secondProgressWithColorDrawable = Progress(indeterminateDrawable = colorDrawable)
val firstProgressWithColor = Progress(color = color)
val secondProgressWithColor = Progress(color = color)
val firstProgressWithBothParams = Progress(indeterminateDrawable = colorDrawable, color = color)
val firstProgressWithColorDrawable = ExperimentalProgress(indeterminateDrawable = colorDrawable)
val secondProgressWithColorDrawable =
ExperimentalProgress(indeterminateDrawable = colorDrawable)
val firstProgressWithColor = ExperimentalProgress(color = color)
val secondProgressWithColor = ExperimentalProgress(color = color)
val firstProgressWithBothParams =
ExperimentalProgress(indeterminateDrawable = colorDrawable, color = color)
val secondProgressWithBothParams =
Progress(indeterminateDrawable = colorDrawable, color = color)
ExperimentalProgress(indeterminateDrawable = colorDrawable, color = color)

assertThat(firstProgressWithColorDrawable).isEquivalentTo(secondProgressWithColorDrawable)
assertThat(firstProgressWithColorDrawable).isEquivalentTo(secondProgressWithColorDrawable, true)
Expand Down

0 comments on commit d4e82f9

Please sign in to comment.