,Fixed image preview not rebinding

This commit is contained in:
vyaivanove
2023-03-15 00:33:04 +03:00
parent e677a3160f
commit 2e16e9aab3
3 changed files with 60 additions and 26 deletions
@@ -55,10 +55,10 @@ internal class DivImageBinder @Inject constructor(
div.scale.observeAndGet(expressionResolver) { scale -> view.imageScale = scale.toImageScale() }
)
view.observeContentAlignment(expressionResolver, div.contentAlignmentHorizontal, div.contentAlignmentVertical)
view.observePreview(divView, expressionResolver, errorCollector, div)
view.addSubscription(
div.imageUrl.observeAndGet(expressionResolver) { view.applyImage(divView, expressionResolver, errorCollector, div) }
)
view.observePreview(divView, expressionResolver, errorCollector, div)
view.observeTint(expressionResolver, div.tintColor, div.tintMode)
view.observeFilters(div.filters, divView, subscriber, expressionResolver)
}
@@ -122,12 +122,10 @@ internal class DivImageBinder @Inject constructor(
div: DivImage) {
div.preview?.let {
val callback = { _: Any ->
if (!isImageLoaded) {
applyPreview(divView, resolver, div, errorCollector, synchronous = isHighPriorityShow(resolver, this, div))
}
applyPreview(divView, resolver, div, errorCollector, synchronous = isHighPriorityShow(resolver, this, div))
}
addSubscription(it.observe(resolver, callback))
addSubscription(it.observeAndGet(resolver, callback))
}
}
@@ -136,10 +134,24 @@ internal class DivImageBinder @Inject constructor(
div: DivImage,
errorCollector: ErrorCollector,
synchronous: Boolean) {
if (isImageLoaded) {
return
}
val newPreview = div.preview?.evaluate(resolver)
if (preview != null && newPreview == preview) {
return
}
resetPreviewLoaded()
preview = newPreview
placeholderLoader.applyPlaceholder(
this,
errorCollector,
div.preview?.evaluate(resolver),
newPreview,
div.placeholderColor.evaluate(resolver),
synchronous = synchronous,
onSetPlaceholder = { drawable ->
@@ -173,6 +185,7 @@ internal class DivImageBinder @Inject constructor(
val isHighPriorityShowPreview = isHighPriorityShow(resolver, this, div)
resetImageLoaded()
resetPreviewLoaded()
applyPreview(divView, resolver, div, errorCollector, synchronous = isHighPriorityShowPreview)
@@ -25,6 +25,7 @@ internal open class DivImageView @JvmOverloads constructor(
internal var div: DivImage? = null
internal var imageUrl: Uri? = null
internal var preview: String? = null
private var borderDrawer: DivBorderDrawer? = null
override val border: DivBorder?
@@ -51,6 +52,11 @@ internal open class DivImageView @JvmOverloads constructor(
imageUrl = null
}
fun resetPreviewLoaded() {
super.resetImageLoaded()
preview = null
}
override fun setAdjustViewBounds(adjustViewBounds: Boolean) = Unit
override fun setCropToPadding(cropToPadding: Boolean) = Unit
@@ -15,18 +15,7 @@ import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.anyOrNull
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.spy
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.verifyNoMoreInteractions
import org.mockito.kotlin.whenever
import org.mockito.kotlin.*
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
@@ -65,7 +54,13 @@ class DivImageBinderTest : DivBinderTest() {
@Test
fun `bind image when image wasn't previously bound`() {
val (view, divContainer) = createTestDiv("with_action.json")
val (view, _) = createTestDiv("with_action.json")
val divContainer = DivImage(
imageUrl = Uri.parse("https://foo.bar/foo.png").asExpression(),
preview = PREVIEW.asExpression(),
highPriorityPreviewShow = true.asExpression()
)
binder.bindView(view, divContainer, divView)
@@ -75,10 +70,22 @@ class DivImageBinderTest : DivBinderTest() {
@Test
fun `do not rebind image when imageUrl did not change and bitmap was not loaded`() {
val (view, divContainer) = createTestDiv("with_action.json")
val (view, _) = createTestDiv("with_action.json")
val divContainer = DivImage(
imageUrl = Uri.parse("https://foo.bar/foo.png").asExpression(),
preview = PREVIEW.asExpression(),
highPriorityPreviewShow = true.asExpression()
)
binder.bindView(view, divContainer, divView)
val (_, nextDivContainer) = createTestDiv("with_action.json")
val nextDivContainer = DivImage(
imageUrl = Uri.parse("https://foo.bar/foo.png").asExpression(),
preview = PREVIEW.asExpression(),
highPriorityPreviewShow = true.asExpression()
)
binder.bindView(view, nextDivContainer, divView)
verify(placeholderLoader).applyPlaceholder(any(), any(), anyOrNull(), any(), any(), any(), any())
@@ -90,6 +97,7 @@ class DivImageBinderTest : DivBinderTest() {
val (view, divContainer) = createTestDiv("with_action.json")
binder.bindView(view, divContainer, divView)
reset(placeholderLoader)
whenImageLoaded(divContainer.imageUrl.evaluate(ExpressionResolver.EMPTY).toString())
@@ -101,7 +109,13 @@ class DivImageBinderTest : DivBinderTest() {
@Test
fun `bind image when bitmap was loaded but imageUrl changed`() {
val (view, divContainer) = createTestDiv("with_action.json")
val (view, _) = createTestDiv("with_action.json")
val divContainer = DivImage(
imageUrl = Uri.parse("https://foo.bar/foo.png").asExpression(),
preview = PREVIEW.asExpression(),
highPriorityPreviewShow = true.asExpression()
)
binder.bindView(view, divContainer, divView)
@@ -110,7 +124,7 @@ class DivImageBinderTest : DivBinderTest() {
val nextDivContainer = DivImage(imageUrl = Uri.parse("https://foo.bar/foo.png").asExpression())
binder.bindView(view, nextDivContainer, divView)
verify(placeholderLoader, times(2)).applyPlaceholder(any(), any(), anyOrNull(), any(), any(), any(), any())
verify(placeholderLoader).applyPlaceholder(any(), any(), anyOrNull(), any(), any(), any(), any())
verify(imageLoader).loadImage(eq(nextDivContainer.imageUrl.evaluate(ExpressionResolver.EMPTY).toString()), any<DivImageDownloadCallback>())
}
@@ -120,6 +134,7 @@ class DivImageBinderTest : DivBinderTest() {
val divContainer = DivImage(
imageUrl = Uri.parse("https://foo.bar/foo.png").asExpression(),
preview = PREVIEW.asExpression(),
highPriorityPreviewShow = true.asExpression()
)
binder.bindView(view, divContainer, divView)
@@ -132,6 +147,7 @@ class DivImageBinderTest : DivBinderTest() {
val nextDivContainer = DivImage(
imageUrl = Uri.parse("https://foo.bar/bar.png").asExpression(),
preview = PREVIEW.asExpression(),
highPriorityPreviewShow = true.asExpression()
)
binder.bindView(view, nextDivContainer, divView)
@@ -217,11 +233,10 @@ class DivImageBinderTest : DivBinderTest() {
@Test
fun `tint color applied to preview`() {
val preview = "iVBORw0KGgoAAAANSUhEUgAAAEEAAABACAYAAABFqxrgAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAIsSURBVHgB7ZqNbcIwEIXdTsAI6QRtN2CDMgIblA1CJ2g3gE5QOkEYgQ3MBnSDV1s2KjKOf0gVfOY+yUImF8Kdz+aeDiEYhmEYhmEYhjwAJmq0anRqHGA42Plc1I5ycnbieB9SjUbUiF39VHSgnkRN6JVFPjoQE5HJvSiXzvPemxoPdwr1+qzGp3NdB2AhakCntWeVZz22y//IhuJQTiwcxzYRe/fgnIoMSt0OjTPfRuy/I/cHoRKEGPTT/whMUfTuOQ+6yH1yyHYoBsSLor6DsXUNBTVg6oEOabSwlaG9z5c1K0EF/OmBvtWPlco+JKiUz+qLTnG+j0+dX9ogLZDOdcpmZKo7mBT+CjjSuSupPycQsCPyWgHIUnfq9RXh1J8FntXYYHQoRUojX93tAtc/QK3MxWXqzkcHwr/n0uOQPsgae12Ln3XAeZ0ZdJUehqk7zQrUFR5GVndjkSugGme+jdgPUndjkRuE3FQmkfq5Qdg585eI/aMz3wvqwJS7qQdj6xqKWoBf8WmHG3u9T91pJGpolvRkQy4dqDdLkKfuQqxIBwPp6k4LrXXErg0FAyX3IpGh7qztBuGAzT3PqK8XaZ2SKcFA7b1IxLeTRD40u08wQksmOpmiVpeCIjDnRezwvI1eZCAYt9OLVB33vRpzca4+t5Fbq+xF/og8BqV/qUFgtQpWqwZcrlbp9CJj4DK1KlHbX/lAoRc5Bii5FzkmKLEXyTAMwzAMw9wQvznV1eV5FJ3aAAAAAElFTkSuQmCC"
val (view, _) = createTestDiv("with_action.json")
val divContainer = DivImage(
imageUrl = Uri.parse("https://foo.bar/foo.png").asExpression(),
preview = preview.asExpression(),
preview = PREVIEW.asExpression(),
tintColor = Color.parseColor("#ffffff").asExpression())
binder.bindView(view, divContainer, divView)
@@ -232,7 +247,6 @@ class DivImageBinderTest : DivBinderTest() {
private fun whenImageLoaded(imageUrl: String) {
val imageDownloadCallbackCaptor = argumentCaptor<DivImageDownloadCallback>()
verify(placeholderLoader).applyPlaceholder(any(), any(), anyOrNull(), any(), any(), any(), any())
verify(imageLoader).loadImage(eq(imageUrl), imageDownloadCallbackCaptor.capture())
val cachedBitmap = mock<CachedBitmap> {
on { bitmap } doReturn mock()
@@ -257,5 +271,6 @@ class DivImageBinderTest : DivBinderTest() {
companion object {
private const val IMAGE_DIR = "div-image"
private const val PREVIEW = "iVBORw0KGgoAAAANSUhEUgAAAEEAAABACAYAAABFqxrgAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAIsSURBVHgB7ZqNbcIwEIXdTsAI6QRtN2CDMgIblA1CJ2g3gE5QOkEYgQ3MBnSDV1s2KjKOf0gVfOY+yUImF8Kdz+aeDiEYhmEYhmEYhjwAJmq0anRqHGA42Plc1I5ycnbieB9SjUbUiF39VHSgnkRN6JVFPjoQE5HJvSiXzvPemxoPdwr1+qzGp3NdB2AhakCntWeVZz22y//IhuJQTiwcxzYRe/fgnIoMSt0OjTPfRuy/I/cHoRKEGPTT/whMUfTuOQ+6yH1yyHYoBsSLor6DsXUNBTVg6oEOabSwlaG9z5c1K0EF/OmBvtWPlco+JKiUz+qLTnG+j0+dX9ogLZDOdcpmZKo7mBT+CjjSuSupPycQsCPyWgHIUnfq9RXh1J8FntXYYHQoRUojX93tAtc/QK3MxWXqzkcHwr/n0uOQPsgae12Ln3XAeZ0ZdJUehqk7zQrUFR5GVndjkSugGme+jdgPUndjkRuE3FQmkfq5Qdg585eI/aMz3wvqwJS7qQdj6xqKWoBf8WmHG3u9T91pJGpolvRkQy4dqDdLkKfuQqxIBwPp6k4LrXXErg0FAyX3IpGh7qztBuGAzT3PqK8XaZ2SKcFA7b1IxLeTRD40u08wQksmOpmiVpeCIjDnRezwvI1eZCAYt9OLVB33vRpzca4+t5Fbq+xF/og8BqV/qUFgtQpWqwZcrlbp9CJj4DK1KlHbX/lAoRc5Bii5FzkmKLEXyTAMwzAMw9wQvznV1eV5FJ3aAAAAAElFTkSuQmCC"
}
}