expo-image 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/android/build.gradle +2 -2
- package/android/src/main/java/expo/modules/image/ExpoImageModule.kt +0 -55
- package/android/src/main/java/expo/modules/image/ExpoImageView.kt +2 -100
- package/android/src/main/java/expo/modules/image/ExpoImageViewWrapper.kt +0 -43
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,18 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 2.0.1 — 2024-11-19
|
|
14
|
+
|
|
15
|
+
### 🐛 Bug fixes
|
|
16
|
+
|
|
17
|
+
- [Android] Fixes Gif animations never stopping even when loop count is set to 1. ([#32944](https://github.com/expo/expo/pull/32944) by [@lukmccall](https://github.com/lukmccall))
|
|
18
|
+
- [Android] Fixed `borderColor` is not applied. ([#33026](https://github.com/expo/expo/pull/33026) by [@lukmccall](https://github.com/lukmccall))
|
|
19
|
+
- [Android] Fixed `border` related props weren't applied correctly. ([#33078](https://github.com/expo/expo/pull/33078) by [@lukmccall](https://github.com/lukmccall))
|
|
20
|
+
|
|
21
|
+
### 💡 Others
|
|
22
|
+
|
|
23
|
+
- [Android] migrate ImageView to CSSBackgroundDrawable ([#33024](https://github.com/expo/expo/pull/33024) by [@vonovak](https://github.com/vonovak))
|
|
24
|
+
|
|
13
25
|
## 2.0.0 — 2024-11-11
|
|
14
26
|
|
|
15
27
|
_This version does not introduce any user-facing changes._
|
package/android/build.gradle
CHANGED
|
@@ -18,7 +18,7 @@ android {
|
|
|
18
18
|
namespace "expo.modules.image"
|
|
19
19
|
defaultConfig {
|
|
20
20
|
versionCode 1
|
|
21
|
-
versionName "2.0.
|
|
21
|
+
versionName "2.0.1"
|
|
22
22
|
consumerProguardFiles("proguard-rules.pro")
|
|
23
23
|
|
|
24
24
|
buildConfigField("boolean", "ALLOW_GLIDE_LOGS", project.properties.get("EXPO_ALLOW_GLIDE_LOGS", "false"))
|
|
@@ -44,7 +44,7 @@ dependencies {
|
|
|
44
44
|
kapt "com.github.bumptech.glide:compiler:${GLIDE_VERSION}"
|
|
45
45
|
api 'com.caverock:androidsvg-aar:1.4'
|
|
46
46
|
|
|
47
|
-
implementation "com.github.penfeizhou.android.animation:glide-plugin:3.0.
|
|
47
|
+
implementation "com.github.penfeizhou.android.animation:glide-plugin:3.0.2"
|
|
48
48
|
implementation "com.github.bumptech.glide:avif-integration:${GLIDE_VERSION}"
|
|
49
49
|
|
|
50
50
|
api 'com.github.bumptech.glide:okhttp3-integration:4.11.0'
|
|
@@ -16,10 +16,6 @@ import com.bumptech.glide.load.model.Headers
|
|
|
16
16
|
import com.bumptech.glide.load.model.LazyHeaders
|
|
17
17
|
import com.bumptech.glide.request.RequestListener
|
|
18
18
|
import com.bumptech.glide.request.target.Target
|
|
19
|
-
import com.facebook.react.uimanager.PixelUtil
|
|
20
|
-
import com.facebook.react.uimanager.Spacing
|
|
21
|
-
import com.facebook.react.uimanager.ViewProps
|
|
22
|
-
import com.facebook.yoga.YogaConstants
|
|
23
19
|
import com.github.penfeizhou.animation.apng.APNGDrawable
|
|
24
20
|
import com.github.penfeizhou.animation.gif.GifDrawable
|
|
25
21
|
import com.github.penfeizhou.animation.webp.WebPDrawable
|
|
@@ -231,57 +227,6 @@ class ExpoImageModule : Module() {
|
|
|
231
227
|
view.transition = transition
|
|
232
228
|
}
|
|
233
229
|
|
|
234
|
-
PropGroup(
|
|
235
|
-
ViewProps.BORDER_RADIUS to 0,
|
|
236
|
-
ViewProps.BORDER_TOP_LEFT_RADIUS to 1,
|
|
237
|
-
ViewProps.BORDER_TOP_RIGHT_RADIUS to 2,
|
|
238
|
-
ViewProps.BORDER_BOTTOM_RIGHT_RADIUS to 3,
|
|
239
|
-
ViewProps.BORDER_BOTTOM_LEFT_RADIUS to 4,
|
|
240
|
-
ViewProps.BORDER_TOP_START_RADIUS to 5,
|
|
241
|
-
ViewProps.BORDER_TOP_END_RADIUS to 6,
|
|
242
|
-
ViewProps.BORDER_BOTTOM_START_RADIUS to 7,
|
|
243
|
-
ViewProps.BORDER_BOTTOM_END_RADIUS to 8
|
|
244
|
-
) { view: ExpoImageViewWrapper, index: Int, borderRadius: Float? ->
|
|
245
|
-
val radius = makeYogaUndefinedIfNegative(borderRadius ?: YogaConstants.UNDEFINED)
|
|
246
|
-
view.setBorderRadius(index, radius)
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
PropGroup(
|
|
250
|
-
ViewProps.BORDER_WIDTH to Spacing.ALL,
|
|
251
|
-
ViewProps.BORDER_LEFT_WIDTH to Spacing.LEFT,
|
|
252
|
-
ViewProps.BORDER_RIGHT_WIDTH to Spacing.RIGHT,
|
|
253
|
-
ViewProps.BORDER_TOP_WIDTH to Spacing.TOP,
|
|
254
|
-
ViewProps.BORDER_BOTTOM_WIDTH to Spacing.BOTTOM,
|
|
255
|
-
ViewProps.BORDER_START_WIDTH to Spacing.START,
|
|
256
|
-
ViewProps.BORDER_END_WIDTH to Spacing.END
|
|
257
|
-
) { view: ExpoImageViewWrapper, index: Int, width: Float? ->
|
|
258
|
-
val pixelWidth = makeYogaUndefinedIfNegative(width ?: YogaConstants.UNDEFINED)
|
|
259
|
-
.ifYogaDefinedUse(PixelUtil::toPixelFromDIP)
|
|
260
|
-
view.setBorderWidth(index, pixelWidth)
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
PropGroup(
|
|
264
|
-
ViewProps.BORDER_COLOR to Spacing.ALL,
|
|
265
|
-
ViewProps.BORDER_LEFT_COLOR to Spacing.LEFT,
|
|
266
|
-
ViewProps.BORDER_RIGHT_COLOR to Spacing.RIGHT,
|
|
267
|
-
ViewProps.BORDER_TOP_COLOR to Spacing.TOP,
|
|
268
|
-
ViewProps.BORDER_BOTTOM_COLOR to Spacing.BOTTOM,
|
|
269
|
-
ViewProps.BORDER_START_COLOR to Spacing.START,
|
|
270
|
-
ViewProps.BORDER_END_COLOR to Spacing.END
|
|
271
|
-
) { view: ExpoImageViewWrapper, index: Int, color: Int? ->
|
|
272
|
-
val rgbComponent = if (color == null) YogaConstants.UNDEFINED.toInt() else (color and 0x00FFFFFF)
|
|
273
|
-
val alphaComponent = if (color == null) YogaConstants.UNDEFINED else (color ushr 24).toFloat()
|
|
274
|
-
view.setBorderColor(index, rgbComponent, alphaComponent)
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
Prop("borderStyle") { view: ExpoImageViewWrapper, borderStyle: String? ->
|
|
278
|
-
view.borderStyle = borderStyle
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
Prop("backgroundColor") { view: ExpoImageViewWrapper, color: Int? ->
|
|
282
|
-
view.backgroundColor = color
|
|
283
|
-
}
|
|
284
|
-
|
|
285
230
|
Prop("tintColor") { view: ExpoImageViewWrapper, color: Int? ->
|
|
286
231
|
view.tintColor = color
|
|
287
232
|
}
|
|
@@ -3,7 +3,6 @@ package expo.modules.image
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.content.Context
|
|
5
5
|
import android.graphics.Canvas
|
|
6
|
-
import android.graphics.Color
|
|
7
6
|
import android.graphics.PorterDuff
|
|
8
7
|
import android.graphics.RectF
|
|
9
8
|
import android.graphics.drawable.BitmapDrawable
|
|
@@ -12,13 +11,11 @@ import android.util.Log
|
|
|
12
11
|
import androidx.appcompat.widget.AppCompatImageView
|
|
13
12
|
import androidx.core.graphics.transform
|
|
14
13
|
import androidx.core.view.isVisible
|
|
15
|
-
import com.facebook.react.
|
|
16
|
-
import com.facebook.react.uimanager.PixelUtil
|
|
17
|
-
import com.facebook.react.views.view.ReactViewBackgroundDrawable
|
|
18
|
-
import expo.modules.image.drawing.OutlineProvider
|
|
14
|
+
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
|
19
15
|
import expo.modules.image.enums.ContentFit
|
|
20
16
|
import expo.modules.image.records.ContentPosition
|
|
21
17
|
|
|
18
|
+
@OptIn(UnstableReactNativeAPI::class)
|
|
22
19
|
@SuppressLint("ViewConstructor")
|
|
23
20
|
class ExpoImageView(
|
|
24
21
|
context: Context
|
|
@@ -40,27 +37,8 @@ class ExpoImageView(
|
|
|
40
37
|
return target
|
|
41
38
|
}
|
|
42
39
|
|
|
43
|
-
private val outlineProvider = OutlineProvider(context)
|
|
44
|
-
|
|
45
40
|
private var transformationMatrixChanged = false
|
|
46
41
|
|
|
47
|
-
private val borderDrawableLazyHolder = lazy {
|
|
48
|
-
ReactViewBackgroundDrawable(context).apply {
|
|
49
|
-
callback = this@ExpoImageView
|
|
50
|
-
|
|
51
|
-
outlineProvider.borderRadiiConfig
|
|
52
|
-
.map { it.ifYogaDefinedUse(PixelUtil::toPixelFromDIP) }
|
|
53
|
-
.withIndex()
|
|
54
|
-
.forEach { (i, radius) ->
|
|
55
|
-
if (i == 0) {
|
|
56
|
-
setRadius(radius)
|
|
57
|
-
} else {
|
|
58
|
-
setRadius(radius, i - 1)
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
42
|
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
|
65
43
|
super.onLayout(changed, left, top, right, bottom)
|
|
66
44
|
applyTransformationMatrix()
|
|
@@ -106,13 +84,9 @@ class ExpoImageView(
|
|
|
106
84
|
}
|
|
107
85
|
}
|
|
108
86
|
|
|
109
|
-
private val borderDrawable
|
|
110
|
-
get() = borderDrawableLazyHolder.value
|
|
111
|
-
|
|
112
87
|
init {
|
|
113
88
|
clipToOutline = true
|
|
114
89
|
scaleType = ScaleType.MATRIX
|
|
115
|
-
super.setOutlineProvider(outlineProvider)
|
|
116
90
|
}
|
|
117
91
|
|
|
118
92
|
// region Component Props
|
|
@@ -134,65 +108,11 @@ class ExpoImageView(
|
|
|
134
108
|
transformationMatrixChanged = true
|
|
135
109
|
}
|
|
136
110
|
|
|
137
|
-
internal fun setBorderRadius(position: Int, borderRadius: Float) {
|
|
138
|
-
val isInvalidated = outlineProvider.setBorderRadius(borderRadius, position)
|
|
139
|
-
if (isInvalidated) {
|
|
140
|
-
invalidateOutline()
|
|
141
|
-
if (!outlineProvider.hasEqualCorners()) {
|
|
142
|
-
invalidate()
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Setting the border-radius doesn't necessarily mean that a border
|
|
147
|
-
// should to be drawn. Only update the border-drawable when needed.
|
|
148
|
-
if (borderDrawableLazyHolder.isInitialized()) {
|
|
149
|
-
val radius = borderRadius.ifYogaDefinedUse(PixelUtil::toPixelFromDIP)
|
|
150
|
-
borderDrawableLazyHolder.value.apply {
|
|
151
|
-
if (position == 0) {
|
|
152
|
-
setRadius(radius)
|
|
153
|
-
} else {
|
|
154
|
-
setRadius(radius, position - 1)
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
internal fun setBorderWidth(position: Int, width: Float) {
|
|
161
|
-
borderDrawable.setBorderWidth(position, width)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
internal fun setBorderColor(position: Int, rgb: Int) {
|
|
165
|
-
borderDrawable.setBorderColor(position, rgb)
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
internal fun setBorderStyle(style: String?) {
|
|
169
|
-
borderDrawable.setBorderStyle(style)
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
internal fun setBackgroundColor(color: Int?) {
|
|
173
|
-
if (color == null) {
|
|
174
|
-
setBackgroundColor(Color.TRANSPARENT)
|
|
175
|
-
} else {
|
|
176
|
-
setBackgroundColor(color)
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
111
|
internal fun setTintColor(color: Int?) {
|
|
181
112
|
color?.let { setColorFilter(it, PorterDuff.Mode.SRC_IN) } ?: clearColorFilter()
|
|
182
113
|
}
|
|
183
114
|
|
|
184
|
-
override fun invalidateDrawable(drawable: Drawable) {
|
|
185
|
-
super.invalidateDrawable(drawable)
|
|
186
|
-
if (borderDrawableLazyHolder.isInitialized() && drawable === borderDrawable) {
|
|
187
|
-
invalidate()
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
115
|
override fun draw(canvas: Canvas) {
|
|
192
|
-
// When the border-radii are not all the same, a convex-path
|
|
193
|
-
// is used for the Outline. Unfortunately clipping is not supported
|
|
194
|
-
// for convex-paths and we fallback to Canvas clipping.
|
|
195
|
-
outlineProvider.clipCanvasIfNeeded(canvas, this)
|
|
196
116
|
// If we encounter a recycled bitmap here, it suggests an issue where we may have failed to
|
|
197
117
|
// finish clearing the image bitmap before the UI attempts to display it.
|
|
198
118
|
// One solution could be to suppress the error and assume that the second image view is currently responsible for displaying the correct view.
|
|
@@ -206,22 +126,4 @@ class ExpoImageView(
|
|
|
206
126
|
}
|
|
207
127
|
super.draw(canvas)
|
|
208
128
|
}
|
|
209
|
-
|
|
210
|
-
public override fun onDraw(canvas: Canvas) {
|
|
211
|
-
super.onDraw(canvas)
|
|
212
|
-
// Draw borders on top of the background and image
|
|
213
|
-
if (borderDrawableLazyHolder.isInitialized()) {
|
|
214
|
-
val newLayoutDirection = if (I18nUtil.instance.isRTL(context)) {
|
|
215
|
-
LAYOUT_DIRECTION_RTL
|
|
216
|
-
} else {
|
|
217
|
-
LAYOUT_DIRECTION_LTR
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
borderDrawable.apply {
|
|
221
|
-
layoutDirection = newLayoutDirection
|
|
222
|
-
setBounds(0, 0, width, height)
|
|
223
|
-
draw(canvas)
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
129
|
}
|
|
@@ -18,7 +18,6 @@ import com.bumptech.glide.RequestManager
|
|
|
18
18
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
|
19
19
|
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
|
|
20
20
|
import com.bumptech.glide.request.RequestOptions
|
|
21
|
-
import com.facebook.yoga.YogaConstants
|
|
22
21
|
import expo.modules.image.enums.ContentFit
|
|
23
22
|
import expo.modules.image.enums.Priority
|
|
24
23
|
import expo.modules.image.events.GlideRequestListener
|
|
@@ -115,18 +114,6 @@ class ExpoImageViewWrapper(context: Context, appContext: AppContext) : ExpoView(
|
|
|
115
114
|
transformationMatrixChanged = true
|
|
116
115
|
}
|
|
117
116
|
|
|
118
|
-
internal var borderStyle: String? = null
|
|
119
|
-
set(value) {
|
|
120
|
-
field = value
|
|
121
|
-
activeView.setBorderStyle(value)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
internal var backgroundColor: Int? = null
|
|
125
|
-
set(value) {
|
|
126
|
-
field = value
|
|
127
|
-
activeView.setBackgroundColor(value)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
117
|
internal var tintColor: Int? = null
|
|
131
118
|
set(value) {
|
|
132
119
|
field = value
|
|
@@ -179,25 +166,6 @@ class ExpoImageViewWrapper(context: Context, appContext: AppContext) : ExpoView(
|
|
|
179
166
|
internal var priority: Priority = Priority.NORMAL
|
|
180
167
|
internal var cachePolicy: CachePolicy = CachePolicy.DISK
|
|
181
168
|
|
|
182
|
-
private var borderRadius = FloatArray(9) { YogaConstants.UNDEFINED }
|
|
183
|
-
private var borderWidth = FloatArray(9) { YogaConstants.UNDEFINED }
|
|
184
|
-
private var borderColor = Array(9) { YogaConstants.UNDEFINED.toInt() to YogaConstants.UNDEFINED }
|
|
185
|
-
|
|
186
|
-
fun setBorderRadius(index: Int, radius: Float) {
|
|
187
|
-
borderRadius[index] = radius
|
|
188
|
-
activeView.setBorderRadius(index, radius)
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
fun setBorderWidth(index: Int, width: Float) {
|
|
192
|
-
borderWidth[index] = width
|
|
193
|
-
activeView.setBorderWidth(index, width)
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
fun setBorderColor(index: Int, rgb: Int, alpha: Float) {
|
|
197
|
-
borderColor[index] = rgb to alpha
|
|
198
|
-
activeView.setBorderColor(index, rgb)
|
|
199
|
-
}
|
|
200
|
-
|
|
201
169
|
fun setIsAnimating(setAnimating: Boolean) {
|
|
202
170
|
val resource = activeView.drawable
|
|
203
171
|
|
|
@@ -237,20 +205,9 @@ class ExpoImageViewWrapper(context: Context, appContext: AppContext) : ExpoView(
|
|
|
237
205
|
private fun copyProps(view: ExpoImageView) {
|
|
238
206
|
view.contentFit = contentFit
|
|
239
207
|
view.contentPosition = contentPosition
|
|
240
|
-
view.setBorderStyle(borderStyle)
|
|
241
|
-
view.setBackgroundColor(backgroundColor)
|
|
242
208
|
view.setTintColor(tintColor)
|
|
243
209
|
view.isFocusable = isFocusableProp
|
|
244
210
|
view.contentDescription = accessibilityLabel
|
|
245
|
-
borderColor.forEachIndexed { index, (rgb, alpha) ->
|
|
246
|
-
view.setBorderColor(index, rgb)
|
|
247
|
-
}
|
|
248
|
-
borderRadius.forEachIndexed { index, value ->
|
|
249
|
-
view.setBorderRadius(index, value)
|
|
250
|
-
}
|
|
251
|
-
borderWidth.forEachIndexed { index, value ->
|
|
252
|
-
view.setBorderWidth(index, value)
|
|
253
|
-
}
|
|
254
211
|
setIsScreenReaderFocusable(view, accessible)
|
|
255
212
|
}
|
|
256
213
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-image",
|
|
3
3
|
"title": "Expo Image",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.1",
|
|
5
5
|
"description": "A cross-platform, performant image component for React Native and Expo with Web support",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"types": "build/index.d.ts",
|
|
@@ -41,5 +41,5 @@
|
|
|
41
41
|
"optional": true
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "128718d43bac2eaed764b3551469b95400f2363e"
|
|
45
45
|
}
|