@sbaiahmed1/react-native-blur 4.5.5-beta.3 → 4.5.5-beta.5

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.
@@ -1,6 +1,8 @@
1
1
  package com.sbaiahmed1.reactnativeblur
2
2
 
3
+ import android.app.Activity
3
4
  import android.content.Context
5
+ import android.content.ContextWrapper
4
6
  import android.graphics.Color
5
7
  import android.graphics.Outline
6
8
  import android.util.AttributeSet
@@ -10,6 +12,7 @@ import android.view.View
10
12
  import android.view.ViewGroup
11
13
  import android.view.ViewOutlineProvider
12
14
  import android.view.ViewTreeObserver
15
+ import com.facebook.react.bridge.ReactContext
13
16
  import com.qmdeve.blurview.widget.BlurViewGroup
14
17
  import com.qmdeve.blurview.base.BaseBlurViewGroup
15
18
  import androidx.core.graphics.toColorInt
@@ -188,10 +191,13 @@ class ReactNativeBlurView : BlurViewGroup {
188
191
 
189
192
  /**
190
193
  * Finds the optimal view to use as blur capture root.
191
- * Priority: nearest react-native-screens Screen > android.R.id.content > parent
194
+ * Priority: nearest react-native-screens Screen > android.R.id.content in parent chain > activity content > parent
195
+ *
196
+ * This handles both regular screens and modals — modals have their own window/view tree,
197
+ * so we walk up the parent chain for android.R.id.content before falling back to the activity.
192
198
  */
193
199
  private fun findOptimalBlurRoot(): ViewGroup? {
194
- return findNearestScreenAncestor() ?: getContentViewFallback()
200
+ return findNearestScreenAncestor() ?: getAppRootFallback()
195
201
  }
196
202
 
197
203
  /**
@@ -210,18 +216,45 @@ class ReactNativeBlurView : BlurViewGroup {
210
216
  }
211
217
 
212
218
  /**
213
- * Falls back to android.R.id.content or the activity root view.
219
+ * Walks up the view parent chain looking for android.R.id.content (works in modals
220
+ * which have their own content root), then falls back to the activity's content view.
214
221
  */
215
- private fun getContentViewFallback(): ViewGroup? {
222
+ private fun getAppRootFallback(): ViewGroup? {
223
+ // Walk up the parent chain — catches modals which have their own android.R.id.content
224
+ var parent = this.parent
225
+ while (parent != null) {
226
+ if (parent is ViewGroup && parent.id == android.R.id.content) {
227
+ return parent
228
+ }
229
+ parent = parent.parent
230
+ }
231
+
232
+ // Fall back to the activity's content view
216
233
  try {
217
- val activity = context as? android.app.Activity
234
+ val activity = getActivityFromContext()
218
235
  activity?.findViewById<ViewGroup>(android.R.id.content)?.let { return it }
219
236
  } catch (e: Exception) {
220
- logDebug("Could not access activity content view: ${e.message}")
237
+ logDebug("Could not access activity root view: ${e.message}")
221
238
  }
239
+
222
240
  return this.parent as? ViewGroup
223
241
  }
224
242
 
243
+ /**
244
+ * Resolves an Activity from the view's context.
245
+ * Priority: ReactContext.currentActivity > ContextWrapper unwrap chain.
246
+ */
247
+ private fun getActivityFromContext(): Activity? {
248
+ (context as? ReactContext)?.currentActivity?.let { return it }
249
+
250
+ var ctx: Context? = context
251
+ while (ctx != null) {
252
+ if (ctx is Activity) return ctx
253
+ ctx = (ctx as? ContextWrapper)?.baseContext
254
+ }
255
+ return null
256
+ }
257
+
225
258
  /**
226
259
  * Initialize the blur view with current settings.
227
260
  * Called after the view is attached and the blur root has been swapped.
@@ -160,7 +160,9 @@ class ReactNativeProgressiveBlurView : FrameLayout {
160
160
  * Redirects the internal BlurView's blur capture root from the activity decor view
161
161
  * to the nearest react-native-screens Screen ancestor.
162
162
  *
163
- * BaseBlurView has public mDecorView and preDrawListener fields, so no reflection needed.
163
+ * BaseBlurView (QmBlurView 1.1.4) field visibility:
164
+ * public — mDecorView, mDifferentRoot, preDrawListener (direct access)
165
+ * private — mForceRedraw (requires reflection)
164
166
  */
165
167
  private fun swapBlurRootToScreenAncestor() {
166
168
  val bv = blurView ?: return
@@ -178,15 +180,24 @@ class ReactNativeProgressiveBlurView : FrameLayout {
178
180
  logDebug("Could not remove old pre-draw listener: ${e.message}")
179
181
  }
180
182
 
181
- // Set new root
183
+ // Set new root (public field)
182
184
  bv.mDecorView = newRoot
183
185
 
184
186
  // Add listener to new root
185
187
  newRoot.viewTreeObserver.addOnPreDrawListener(listener)
186
188
 
187
- // Update mDifferentRoot flag
189
+ // Update mDifferentRoot flag (public field)
188
190
  bv.mDifferentRoot = newRoot.rootView != bv.rootView
189
191
 
192
+ // Force a redraw (private field — requires reflection)
193
+ try {
194
+ val forceRedrawField = bv.javaClass.superclass.getDeclaredField("mForceRedraw")
195
+ forceRedrawField.isAccessible = true
196
+ forceRedrawField.setBoolean(bv, true)
197
+ } catch (e: NoSuchFieldException) {
198
+ logWarning("Could not set mForceRedraw via reflection: ${e.message}")
199
+ }
200
+
190
201
  logDebug("Progressive blur: swapped root to ${newRoot.javaClass.simpleName}")
191
202
  }
192
203
  } catch (e: Exception) {
@@ -196,10 +207,13 @@ class ReactNativeProgressiveBlurView : FrameLayout {
196
207
 
197
208
  /**
198
209
  * Finds the optimal view to use as blur capture root.
199
- * Priority: nearest react-native-screens Screen > android.R.id.content > parent
210
+ * Priority: nearest react-native-screens Screen > android.R.id.content in parent chain > activity content > parent
211
+ *
212
+ * This handles both regular screens and modals — modals have their own window/view tree,
213
+ * so we walk up the parent chain for android.R.id.content before falling back to the activity.
200
214
  */
201
215
  private fun findOptimalBlurRoot(): ViewGroup? {
202
- return findNearestScreenAncestor() ?: getContentViewFallback()
216
+ return findNearestScreenAncestor() ?: getAppRootFallback()
203
217
  }
204
218
 
205
219
  /**
@@ -217,16 +231,27 @@ class ReactNativeProgressiveBlurView : FrameLayout {
217
231
  }
218
232
 
219
233
  /**
220
- * Falls back to android.R.id.content or the activity root view.
221
- * Tries ReactContext.currentActivity first, then unwraps ContextWrapper chain.
234
+ * Walks up the view parent chain looking for android.R.id.content (works in modals
235
+ * which have their own content root), then falls back to the activity's content view.
222
236
  */
223
- private fun getContentViewFallback(): ViewGroup? {
237
+ private fun getAppRootFallback(): ViewGroup? {
238
+ // Walk up the parent chain — catches modals which have their own android.R.id.content
239
+ var parent = this.parent
240
+ while (parent != null) {
241
+ if (parent is ViewGroup && parent.id == android.R.id.content) {
242
+ return parent
243
+ }
244
+ parent = parent.parent
245
+ }
246
+
247
+ // Fall back to the activity's content view
224
248
  try {
225
249
  val activity = getActivityFromContext()
226
250
  activity?.findViewById<ViewGroup>(android.R.id.content)?.let { return it }
227
251
  } catch (e: Exception) {
228
- logDebug("Could not access activity content view: ${e.message}")
252
+ logDebug("Could not access activity root view: ${e.message}")
229
253
  }
254
+
230
255
  return this.parent as? ViewGroup
231
256
  }
232
257
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sbaiahmed1/react-native-blur",
3
- "version": "4.5.5-beta.3",
3
+ "version": "4.5.5-beta.5",
4
4
  "description": "React native modern blur view",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",