@@ -21,7 +21,18 @@ import android.provider.MediaStore
2121import android.text.TextUtils
2222import android.util.Base64
2323import androidx.exifinterface.media.ExifInterface
24+ import com.facebook.common.executors.CallerThreadExecutor
2425import com.facebook.common.logging.FLog
26+ import com.facebook.common.memory.PooledByteBuffer
27+ import com.facebook.common.memory.PooledByteBufferInputStream
28+ import com.facebook.common.references.CloseableReference
29+ import com.facebook.datasource.BaseDataSubscriber
30+ import com.facebook.datasource.DataSource
31+ import com.facebook.datasource.DataSubscriber
32+ import com.facebook.drawee.backends.pipeline.Fresco
33+ import com.facebook.imagepipeline.core.ImagePipeline
34+ import com.facebook.imagepipeline.request.ImageRequest
35+ import com.facebook.imagepipeline.request.ImageRequestBuilder
2536import com.facebook.infer.annotation.Assertions
2637import com.facebook.react.bridge.Arguments
2738import com.facebook.react.bridge.JSApplicationIllegalArgumentException
@@ -31,6 +42,8 @@ import com.facebook.react.bridge.ReadableMap
3142import com.facebook.react.bridge.ReadableType
3243import com.facebook.react.bridge.WritableMap
3344import com.facebook.react.common.ReactConstants
45+ import com.facebook.react.modules.fresco.ReactNetworkImageRequest
46+ import com.facebook.react.views.image.ReactCallerContextFactory
3447import java.io.ByteArrayInputStream
3548import java.io.File
3649import java.io.FileInputStream
@@ -51,7 +64,13 @@ object MimeType {
5164 const val WEBP = " image/webp"
5265}
5366
54- class ImageEditorModuleImpl (private val reactContext : ReactApplicationContext ) {
67+ class ImageEditorModuleImpl (
68+ private val reactContext : ReactApplicationContext ,
69+ private val callerContext : Any? ,
70+ private val callerContextFactory : ReactCallerContextFactory ? ,
71+ private val imagePipeline : ImagePipeline ?
72+ ) {
73+
5574 private val moduleCoroutineScope = CoroutineScope (Dispatchers .Default )
5675
5776 init {
@@ -65,6 +84,58 @@ class ImageEditorModuleImpl(private val reactContext: ReactApplicationContext) {
6584 cleanTask()
6685 }
6786
87+ private fun getCallerContext (): Any? {
88+ return callerContextFactory?.getOrCreateCallerContext(" " , " " ) ? : callerContext
89+ }
90+
91+ private fun getImagePipeline (): ImagePipeline {
92+ return imagePipeline ? : Fresco .getImagePipeline()
93+ }
94+
95+ private fun fetchAndCacheImage (
96+ uri : String ,
97+ headers : ReadableMap ? ,
98+ callback : (InputStream ? ) -> Unit
99+ ) {
100+ val uri = Uri .parse(uri)
101+
102+ val imageRequest: ImageRequest =
103+ if (headers != null ) {
104+ val imageRequestBuilder = ImageRequestBuilder .newBuilderWithSource(uri)
105+ ReactNetworkImageRequest .fromBuilderWithHeaders(imageRequestBuilder, headers)
106+ } else ImageRequestBuilder .newBuilderWithSource(uri).build()
107+
108+ val dataSource: DataSource <CloseableReference <PooledByteBuffer >> =
109+ getImagePipeline().fetchEncodedImage(imageRequest, getCallerContext())
110+ val dataSubscriber: DataSubscriber <CloseableReference <PooledByteBuffer >> =
111+ object : BaseDataSubscriber <CloseableReference <PooledByteBuffer >>() {
112+ override fun onNewResultImpl (
113+ dataSource : DataSource <CloseableReference <PooledByteBuffer >>
114+ ) {
115+ if (! dataSource.isFinished()) {
116+ return
117+ }
118+ val ref = dataSource.getResult()
119+ val result = ref?.get()
120+ if (result != null ) {
121+ val stream: InputStream = PooledByteBufferInputStream (result)
122+ callback(stream)
123+ } else {
124+ dataSource.close()
125+ callback(null )
126+ }
127+ }
128+
129+ override fun onFailureImpl (
130+ dataSource : DataSource <CloseableReference <PooledByteBuffer >>
131+ ) {
132+ dataSource.close()
133+ callback(null )
134+ }
135+ }
136+ dataSource.subscribe(dataSubscriber, CallerThreadExecutor .getInstance())
137+ }
138+
68139 /* *
69140 * Asynchronous task that cleans up cache dirs (internal and, if available, external) of cropped
70141 * image files. This is run when the module is invalidated (i.e. app is shutting down) and when
@@ -148,7 +219,7 @@ class ImageEditorModuleImpl(private val reactContext: ReactApplicationContext) {
148219 // memory
149220 val hasTargetSize = targetWidth > 0 && targetHeight > 0
150221 val cropped: Bitmap ? =
151- if (hasTargetSize) {
222+ if (hasTargetSize)
152223 cropAndResizeTask(
153224 outOptions,
154225 uri,
@@ -160,9 +231,8 @@ class ImageEditorModuleImpl(private val reactContext: ReactApplicationContext) {
160231 targetHeight,
161232 headers
162233 )
163- } else {
164- cropTask(outOptions, uri, x, y, width, height, headers)
165- }
234+ else cropTask(outOptions, uri, x, y, width, height, headers)
235+
166236 if (cropped == null ) {
167237 throw IOException (" Cannot decode bitmap: $uri " )
168238 }
0 commit comments