react-native-multiple-image-picker icon indicating copy to clipboard operation
react-native-multiple-image-picker copied to clipboard

RN 0.81.1, multiple-image-picker 2.2.4, nitro-modules 0.29.6 - ios, android build error Troubleshooting

Open qnrjs42 opened this issue 2 months ago • 3 comments

package.json

"@baronha/react-native-multiple-image-picker": "2.2.4",
"react-native": "0.81.1",
"react-native-nitro-modules": "0.29.6",

ios/Podfile

target 'my_app' do
  config = use_native_modules!

  pod 'Kingfisher', '8.5.0'

  use_react_native!(
    :path => config[:reactNativePath],
    # An absolute path to your application root.
    :app_path => "#{Pod::Config.instance.installation_root}/.."
  )

  post_install do |installer|
    # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
    react_native_post_install(
      installer,
      config[:reactNativePath],
      :mac_catalyst_enabled => false,
      # :ccache_enabled => true
    )

    installer.pods_project.targets.each do |target|
      if target.name == 'Kingfisher'
        target.build_configurations.each do |config|
          config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'NO'
        end
      end
    end
  end
end

patches/@baronha__react-native-multiple-image-picker.patch

diff --git a/android/src/main/java/com/margelo/nitro/multipleimagepicker/CameraEngine.kt b/android/src/main/java/com/margelo/nitro/multipleimagepicker/CameraEngine.kt
index 282bdccd6c2f263be84ba0886a01261ba71c7f5b..e0745624a83d02477f1be9a1635c44585e0b9596 100644
--- a/android/src/main/java/com/margelo/nitro/multipleimagepicker/CameraEngine.kt
+++ b/android/src/main/java/com/margelo/nitro/multipleimagepicker/CameraEngine.kt
@@ -30,7 +30,7 @@ class CameraEngine(
         camera.setOutputPathDir(getSandboxCameraOutputPath())
 
         config.color?.let {
-            val primaryColor = ColorPropConverter.getColor(it, appContext)
+            val primaryColor = ColorPropConverter.getColor(it, appContext) ?: 0
             camera.setCaptureLoadingColor(primaryColor)
         }
 
diff --git a/android/src/main/java/com/margelo/nitro/multipleimagepicker/MultipleImagePickerImp.kt b/android/src/main/java/com/margelo/nitro/multipleimagepicker/MultipleImagePickerImp.kt
index 5c4d8ba1f716c05b29f3ad9a82664d931e77cc53..840d18a5a797d84aa77d612d8f269cb483ec0c61 100644
--- a/android/src/main/java/com/margelo/nitro/multipleimagepicker/MultipleImagePickerImp.kt
+++ b/android/src/main/java/com/margelo/nitro/multipleimagepicker/MultipleImagePickerImp.kt
@@ -9,8 +9,6 @@ import androidx.core.content.ContextCompat
 import com.facebook.react.bridge.BaseActivityEventListener
 import com.facebook.react.bridge.ColorPropConverter
 import com.facebook.react.bridge.ReactApplicationContext
-import com.facebook.react.bridge.ReactContextBaseJavaModule
-import com.facebook.react.bridge.ReactMethod
 import com.luck.picture.lib.app.IApp
 import com.luck.picture.lib.app.PictureAppMaster
 import com.luck.picture.lib.basic.PictureSelector
@@ -41,31 +39,28 @@ import java.net.HttpURLConnection
 import java.net.URL
 
 
-class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
-    ReactContextBaseJavaModule(reactContext), IApp {
-
-    override fun getName(): String {
-        return "MultipleImagePicker"
-    }
+class MultipleImagePickerImp(private val reactContext: ReactApplicationContext?) : IApp {
 
     companion object {
         const val TAG = "MultipleImagePicker"
     }
 
+    private val context: Context
+        get() = reactContext ?: throw IllegalStateException("React context is null")
+
     private var style = PictureSelectorStyle()
     private lateinit var config: NitroConfig
     private var cropOption = Options()
     private var dataList = mutableListOf<LocalMedia>()
 
 
-    @ReactMethod
     fun openPicker(
         options: NitroConfig,
         resolved: (result: Array<PickerResult>) -> Unit,
         rejected: (reject: Double) -> Unit
     ) {
         PictureAppMaster.getInstance().app = this
-        val activity = currentActivity
+        val activity = reactContext?.currentActivity
         val imageEngine = GlideEngine.createGlideEngine()
 
         // set global config
@@ -126,7 +121,7 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
                         videoMaximumDuration = it.videoMaximumDuration
                     )
 
-                    setCameraInterceptListener(CameraEngine(appContext, cameraConfig))
+                    setCameraInterceptListener(CameraEngine(context, cameraConfig))
                 }
             }
             .setVideoThumbnailListener(VideoThumbnailEngine(getVideoThumbnailDir()))
@@ -175,7 +170,6 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
             })
     }
 
-    @ReactMethod
     fun openCrop(
         image: String,
         options: NitroCropConfig,
@@ -205,7 +199,7 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
 
                     val inputStream = connection.inputStream
                     // Create a temp file to store the image
-                    val file = File(appContext.cacheDir, "CROP_")
+                    val file = File(context.cacheDir, "CROP_")
                     file.outputStream().use { output ->
                         inputStream.copyTo(output)
                     }
@@ -217,7 +211,7 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
             }
 
             val destinationUri = Uri.fromFile(
-                File(getSandboxPath(appContext), DateUtils.getCreateFileName("CROP_") + ".jpeg")
+                File(getSandboxPath(context), DateUtils.getCreateFileName("CROP_") + ".jpeg")
             )
             val uCrop = UCrop.of<Any>(uri, destinationUri).withOptions(cropOption)
 
@@ -251,20 +245,19 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
                     }
 
                     // Remove listener after getting result
-                    reactApplicationContext.removeActivityEventListener(this)
+                    reactContext?.removeActivityEventListener(this)
                 }
             }
 
             // Add listener before starting UCrop
-            reactApplicationContext.addActivityEventListener(cropActivityEventListener)
+            reactContext?.addActivityEventListener(cropActivityEventListener)
 
-            currentActivity?.let { uCrop.start(it, REQUEST_CROP) }
+            reactContext?.currentActivity?.let { uCrop.start(it, REQUEST_CROP) }
         } catch (e: Exception) {
             rejected(0.0)
         }
     }
 
-    @ReactMethod
     fun openPreview(
         media: Array<MediaPreview>,
         index: Int,
@@ -300,7 +293,7 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
                         ) ?: "image/jpg"
                     asset = localMedia
                 } else {
-                    asset = LocalMedia.generateLocalMedia(appContext, path)
+                    asset = LocalMedia.generateLocalMedia(context, path)
                 }
             }
 
@@ -311,7 +304,7 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
         }
 
         PictureSelector
-            .create(currentActivity)
+            .create(reactContext?.currentActivity)
             .openPreview()
             .setImageEngine(imageEngine)
             .setLanguage(getLanguage(config.language))
@@ -339,20 +332,19 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
         return OnCustomLoadingListener { context -> LoadingDialog(context) }
     }
 
-    @ReactMethod
     fun openCamera(
         config: NitroCameraConfig,
         resolved: (result: CameraResult) -> Unit,
         rejected: (reject: Double) -> Unit
     ) {
-        val activity = currentActivity
+        val activity = reactContext?.currentActivity
         val chooseMode = getChooseMode(config.mediaType)
 
         PictureSelector
             .create(activity)
             .openCamera(chooseMode)
             .setLanguage(getLanguage(config.language))
-            .setCameraInterceptListener(CameraEngine(appContext, config))
+            .setCameraInterceptListener(CameraEngine(context, config))
             .isQuickCapture(true)
             .isOriginalControl(true)
             .setVideoThumbnailListener(VideoThumbnailEngine(getVideoThumbnailDir()))
@@ -395,7 +387,7 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
     }
 
     private fun getVideoThumbnailDir(): String {
-        val externalFilesDir: File? = appContext.getExternalFilesDir("")
+        val externalFilesDir: File? = context.getExternalFilesDir("")
         val customFile = File(externalFilesDir?.absolutePath, "Thumbnail")
         if (!customFile.exists()) {
             customFile.mkdirs()
@@ -424,7 +416,7 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
         cropOption.setShowCropFrame(true)
         cropOption.setShowCropGrid(true)
         cropOption.setCircleDimmedLayer(config?.circle ?: false)
-        cropOption.setCropOutputPathDir(getSandboxPath(appContext))
+        cropOption.setCropOutputPathDir(getSandboxPath(context))
         cropOption.isCropDragSmoothToCenter(true)
         cropOption.isForbidSkipMultipleCrop(true)
         cropOption.setMaxScaleMultiplier(100f)
@@ -481,19 +473,19 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
 
 
     private fun setEditMediaEvent(): OnMediaEditInterceptListener {
-        return MediaEditInterceptListener(getSandboxPath(appContext), cropOption)
+        return MediaEditInterceptListener(getSandboxPath(context), cropOption)
     }
 
     private fun setStyle() {
-        val primaryColor = ColorPropConverter.getColor(config.primaryColor, appContext)
+        val primaryColor = ColorPropConverter.getColor(config.primaryColor, context)
         val isNumber =
             config.selectMode == SelectMode.MULTIPLE && config.selectBoxStyle == SelectBoxStyle.NUMBER
         val selectType = if (isNumber) R.drawable.picture_selector else R.drawable.checkbox_selector
         val isDark = config.theme == Theme.DARK
 
-        val backgroundDark = ColorPropConverter.getColor(config.backgroundDark, appContext)
+        val backgroundDark = ColorPropConverter.getColor(config.backgroundDark, context)
             ?: ContextCompat.getColor(
-                appContext, com.luck.picture.lib.R.color.ps_color_33
+                context, com.luck.picture.lib.R.color.ps_color_33
             )
 
         val foreground = if (isDark) Color.WHITE else Color.BLACK
@@ -505,7 +497,7 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
         val iconBack =
             if (isDark) com.luck.picture.lib.R.drawable.ps_ic_back else com.luck.picture.lib.R.drawable.ps_ic_black_back
 
-        cropOption.setLogoColor(primaryColor)
+        primaryColor?.let { cropOption.setLogoColor(it) }
 
         // TITLE BAR
         titleBar.titleBackgroundColor = background
@@ -529,7 +521,7 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
         mainStyle.isDarkStatusBarBlack = !isDark
         mainStyle.statusBarColor = background
         mainStyle.mainListBackgroundColor = background
-        mainStyle.adapterPreviewGalleryItemSize = DensityUtil.dip2px(appContext, 52f);
+        mainStyle.adapterPreviewGalleryItemSize = DensityUtil.dip2px(context, 52f);
         mainStyle.adapterPreviewGalleryBackgroundResource =
             if (isDark) com.luck.picture.lib.R.drawable.ps_preview_gallery_bg else R.drawable.preview_gallery_white_bg
         mainStyle.adapterPreviewGalleryFrameResource = R.drawable.preview_gallery_item
@@ -547,7 +539,7 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
         mainStyle.isAdapterItemIncludeEdge = true
         mainStyle.isPreviewSelectRelativeBottom = false
 //        mainStyle.previewSelectTextSize = Constant.TOOLBAR_TEXT_SIZE
-        mainStyle.selectTextColor = primaryColor
+        primaryColor?.let { mainStyle.selectTextColor = it }
 //        mainStyle.selectTextSize = Constant.TOOLBAR_TEXT_SIZE
         mainStyle.selectBackground = selectType
         mainStyle.isSelectNumberStyle = isNumber
@@ -645,7 +637,7 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) :
     }
 
     override fun getAppContext(): Context {
-        return reactApplicationContext
+        return context
     }
 
     override fun getPictureSelectorEngine(): PictureSelectorEngine {

qnrjs42 avatar Sep 30 '25 03:09 qnrjs42

What is the error for this patch? @qnrjs42

MohammadAzimi avatar Oct 02 '25 18:10 MohammadAzimi

I think the error is related to using the latest version of react-native-nitro-modules, to get 16kb page size support.

KesoGizmoYoshi avatar Oct 13 '25 13:10 KesoGizmoYoshi

I think the error is related to using the latest version of react-native-nitro-modules, to get 16kb page size support.

No, this doesn't solve the 16KB problem, because the issue remains due to the PictureSelector library.

tarnumius avatar Oct 14 '25 09:10 tarnumius