From c365f139b8e11a579fcf78aff88838ebaa6fd7ba Mon Sep 17 00:00:00 2001 From: "Deepanshu.shukla" Date: Fri, 2 Aug 2024 16:01:21 +0530 Subject: [PATCH 1/2] feat: bridgeless mode --- ReactNativeFastImageExample/src/index.tsx | 3 ++ .../fastimage/FastImageRequestListener.java | 29 +++++++++----- .../fastimage/FastImageViewManager.java | 25 ++++++++---- .../fastimage/FastImageViewWithUrl.java | 39 ++++++++++--------- .../fastimage/events/FastImageErrorEvent.java | 34 ++++++++++++++++ .../events/FastImageLoadEndEvent.java | 19 +++++++++ .../fastimage/events/FastImageLoadEvent.java | 19 +++++++++ .../events/FastImageLoadStartEvent.java | 19 +++++++++ .../events/FastImageProgressEvent.java | 34 ++++++++++++++++ 9 files changed, 185 insertions(+), 36 deletions(-) create mode 100644 android/src/main/java/com/dylanvann/fastimage/events/FastImageErrorEvent.java create mode 100644 android/src/main/java/com/dylanvann/fastimage/events/FastImageLoadEndEvent.java create mode 100644 android/src/main/java/com/dylanvann/fastimage/events/FastImageLoadEvent.java create mode 100644 android/src/main/java/com/dylanvann/fastimage/events/FastImageLoadStartEvent.java create mode 100644 android/src/main/java/com/dylanvann/fastimage/events/FastImageProgressEvent.java diff --git a/ReactNativeFastImageExample/src/index.tsx b/ReactNativeFastImageExample/src/index.tsx index 690ece7..38d2aac 100644 --- a/ReactNativeFastImageExample/src/index.tsx +++ b/ReactNativeFastImageExample/src/index.tsx @@ -13,6 +13,9 @@ LogBox.ignoreLogs([ 'Warning: isMounted(...) is deprecated', 'Module RCTImageLoader', ]); +const uiManager = global?.nativeFabricUIManager ? 'Fabric' : 'Paper'; + +console.log('Running on',uiManager) export default function App() { return ( diff --git a/android/src/main/java/com/dylanvann/fastimage/FastImageRequestListener.java b/android/src/main/java/com/dylanvann/fastimage/FastImageRequestListener.java index dbeb813..3823380 100644 --- a/android/src/main/java/com/dylanvann/fastimage/FastImageRequestListener.java +++ b/android/src/main/java/com/dylanvann/fastimage/FastImageRequestListener.java @@ -8,9 +8,14 @@ import com.bumptech.glide.request.target.ImageViewTarget; import com.bumptech.glide.request.target.Target; import com.facebook.react.bridge.WritableMap; +import com.dylanvann.fastimage.events.FastImageErrorEvent; +import com.dylanvann.fastimage.events.FastImageLoadEndEvent; +import com.dylanvann.fastimage.events.FastImageLoadEvent; +import com.dylanvann.fastimage.events.FastImageProgressEvent; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.events.RCTEventEmitter; +import com.facebook.react.uimanager.UIManagerHelper; +import com.facebook.react.uimanager.events.EventDispatcher; public class FastImageRequestListener implements RequestListener { static final String REACT_ON_ERROR_EVENT = "onFastImageError"; @@ -37,10 +42,13 @@ public boolean onLoadFailed(@androidx.annotation.Nullable GlideException e, Obje } FastImageViewWithUrl view = (FastImageViewWithUrl) ((ImageViewTarget) target).getView(); ThemedReactContext context = (ThemedReactContext) view.getContext(); - RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class); - int viewId = view.getId(); - eventEmitter.receiveEvent(viewId, REACT_ON_ERROR_EVENT, new WritableNativeMap()); - eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_END_EVENT, new WritableNativeMap()); + EventDispatcher dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, view.getId()); + int surfaceId = UIManagerHelper.getSurfaceId(view); + + if (dispatcher != null) { + dispatcher.dispatchEvent(new FastImageErrorEvent(surfaceId, view.getId(), null)); + dispatcher.dispatchEvent(new FastImageLoadEndEvent(surfaceId, view.getId())); + } return false; } @@ -51,10 +59,13 @@ public boolean onResourceReady(Drawable resource, Object model, Target } FastImageViewWithUrl view = (FastImageViewWithUrl) ((ImageViewTarget) target).getView(); ThemedReactContext context = (ThemedReactContext) view.getContext(); - RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class); - int viewId = view.getId(); - eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_EVENT, mapFromResource(resource)); - eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_END_EVENT, new WritableNativeMap()); + EventDispatcher dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, view.getId()); + int surfaceId = UIManagerHelper.getSurfaceId(view); + + if (dispatcher != null) { + dispatcher.dispatchEvent(new FastImageLoadEvent(surfaceId, view.getId())); + dispatcher.dispatchEvent(new FastImageLoadEndEvent(surfaceId, view.getId())); + } return false; } } diff --git a/android/src/main/java/com/dylanvann/fastimage/FastImageViewManager.java b/android/src/main/java/com/dylanvann/fastimage/FastImageViewManager.java index c7a7954..a50f8b0 100644 --- a/android/src/main/java/com/dylanvann/fastimage/FastImageViewManager.java +++ b/android/src/main/java/com/dylanvann/fastimage/FastImageViewManager.java @@ -14,14 +14,19 @@ import com.bumptech.glide.Glide; import com.bumptech.glide.RequestManager; +import com.dylanvann.fastimage.events.FastImageProgressEvent; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.common.MapBuilder; import com.facebook.react.uimanager.SimpleViewManager; import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.UIManagerHelper; +import com.facebook.react.uimanager.common.ViewUtil; +import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.react.uimanager.annotations.ReactProp; -import com.facebook.react.uimanager.events.RCTEventEmitter; import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper; import java.util.List; @@ -117,13 +122,17 @@ public void onProgress(String key, long bytesRead, long expectedLength) { List viewsForKey = VIEWS_FOR_URLS.get(key); if (viewsForKey != null) { for (FastImageViewWithUrl view : viewsForKey) { - WritableMap event = new WritableNativeMap(); - event.putInt("loaded", (int) bytesRead); - event.putInt("total", (int) expectedLength); - ThemedReactContext context = (ThemedReactContext) view.getContext(); - RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class); - int viewId = view.getId(); - eventEmitter.receiveEvent(viewId, REACT_ON_PROGRESS_EVENT, event); + ReactContext context = getReactApplicationContext(); + EventDispatcher dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, view.getId()); + FastImageProgressEvent event = new FastImageProgressEvent( + ViewUtil.NO_SURFACE_ID, + view.getId(), + (int) bytesRead, + (int) expectedLength); + + if (dispatcher != null) { + dispatcher.dispatchEvent(event); + } } } } diff --git a/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java b/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java index 29982b4..33e1f2f 100644 --- a/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java +++ b/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java @@ -14,10 +14,11 @@ import com.bumptech.glide.load.model.GlideUrl; import com.bumptech.glide.request.Request; import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.bridge.WritableNativeMap; +import com.dylanvann.fastimage.events.FastImageErrorEvent; +import com.dylanvann.fastimage.events.FastImageLoadStartEvent; import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.events.RCTEventEmitter; +import com.facebook.react.uimanager.UIManagerHelper; +import com.facebook.react.uimanager.events.EventDispatcher; import java.util.ArrayList; import java.util.Collections; @@ -75,12 +76,9 @@ public void onAfterUpdate( setImageDrawable(null); ThemedReactContext context = (ThemedReactContext) getContext(); - RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class); - int viewId = getId(); - WritableMap event = new WritableNativeMap(); - event.putString("message", "Image source uri cannot be empty or null:" + mSource); - eventEmitter.receiveEvent(viewId, REACT_ON_ERROR_EVENT, event); - + EventDispatcher dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, getId()); + int surfaceId = UIManagerHelper.getSurfaceId(this); + FastImageErrorEvent event = new FastImageErrorEvent(surfaceId, getId(), mSource); return; } @@ -89,12 +87,13 @@ public void onAfterUpdate( if (imageSource != null && imageSource.getUri().toString().length() == 0) { ThemedReactContext context = (ThemedReactContext) getContext(); - RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class); - int viewId = getId(); - WritableMap event = new WritableNativeMap(); - event.putString("message", "Invalid source prop: " + mSource); - eventEmitter.receiveEvent(viewId, REACT_ON_ERROR_EVENT, event); + EventDispatcher dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, getId()); + int surfaceId = UIManagerHelper.getSurfaceId(this); + FastImageErrorEvent event = new FastImageErrorEvent(surfaceId, getId(), mSource); + if (dispatcher != null) { + dispatcher.dispatchEvent(event); + } // Cancel existing requests. clearView(requestManager); @@ -129,12 +128,14 @@ public void onAfterUpdate( ThemedReactContext context = (ThemedReactContext) getContext(); if (imageSource != null) { // This is an orphan even without a load/loadend when only loading a placeholder - RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class); - int viewId = this.getId(); + // This is an orphan event without a load/loadend when only loading a placeholder + EventDispatcher dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, getId()); + int surfaceId = UIManagerHelper.getSurfaceId(this); + FastImageLoadStartEvent event = new FastImageLoadStartEvent(surfaceId, getId()); - eventEmitter.receiveEvent(viewId, - FastImageViewManager.REACT_ON_LOAD_START_EVENT, - new WritableNativeMap()); + if (dispatcher != null) { + dispatcher.dispatchEvent(event); + } } if (requestManager != null) { diff --git a/android/src/main/java/com/dylanvann/fastimage/events/FastImageErrorEvent.java b/android/src/main/java/com/dylanvann/fastimage/events/FastImageErrorEvent.java new file mode 100644 index 0000000..799ddcb --- /dev/null +++ b/android/src/main/java/com/dylanvann/fastimage/events/FastImageErrorEvent.java @@ -0,0 +1,34 @@ +package com.dylanvann.fastimage.events; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.uimanager.events.Event; + +public class FastImageErrorEvent extends Event { + + @Nullable + private final ReadableMap mSource; + + public FastImageErrorEvent(int surfaceId, int viewTag, @Nullable ReadableMap source) { + super(surfaceId, viewTag); + mSource = source; + } + @NonNull + @Override + public String getEventName() { + return "onFastImageError"; + } + + @Override + protected WritableMap getEventData() { + WritableMap eventData = Arguments.createMap(); + if (mSource != null) { + eventData.putString("message", "Invalid source prop:" + mSource); + } + return eventData; + } +} diff --git a/android/src/main/java/com/dylanvann/fastimage/events/FastImageLoadEndEvent.java b/android/src/main/java/com/dylanvann/fastimage/events/FastImageLoadEndEvent.java new file mode 100644 index 0000000..226aff0 --- /dev/null +++ b/android/src/main/java/com/dylanvann/fastimage/events/FastImageLoadEndEvent.java @@ -0,0 +1,19 @@ +package com.dylanvann.fastimage.events; + +import androidx.annotation.NonNull; + +import com.facebook.react.uimanager.events.Event; + +public class FastImageLoadEndEvent extends Event { + + public FastImageLoadEndEvent(int surfaceId, int viewTag) { + super(surfaceId, viewTag); + } + + @NonNull + @Override + public String getEventName() { + return "onFastImageLoadEnd"; + } + +} diff --git a/android/src/main/java/com/dylanvann/fastimage/events/FastImageLoadEvent.java b/android/src/main/java/com/dylanvann/fastimage/events/FastImageLoadEvent.java new file mode 100644 index 0000000..282d931 --- /dev/null +++ b/android/src/main/java/com/dylanvann/fastimage/events/FastImageLoadEvent.java @@ -0,0 +1,19 @@ +package com.dylanvann.fastimage.events; + +import androidx.annotation.NonNull; + +import com.facebook.react.uimanager.events.Event; + +public class FastImageLoadEvent extends Event { + + public FastImageLoadEvent(int surfaceId, int viewTag) { + super(surfaceId, viewTag); + } + + @NonNull + @Override + public String getEventName() { + return "onFastImageLoad"; + } + +} diff --git a/android/src/main/java/com/dylanvann/fastimage/events/FastImageLoadStartEvent.java b/android/src/main/java/com/dylanvann/fastimage/events/FastImageLoadStartEvent.java new file mode 100644 index 0000000..e3f4d82 --- /dev/null +++ b/android/src/main/java/com/dylanvann/fastimage/events/FastImageLoadStartEvent.java @@ -0,0 +1,19 @@ +package com.dylanvann.fastimage.events; + +import androidx.annotation.NonNull; + +import com.facebook.react.uimanager.events.Event; + +public class FastImageLoadStartEvent extends Event { + + public FastImageLoadStartEvent(int surfaceId, int viewTag) { + super(surfaceId, viewTag); + } + + @NonNull + @Override + public String getEventName() { + return "onFastImageLoadStart"; + } + +} diff --git a/android/src/main/java/com/dylanvann/fastimage/events/FastImageProgressEvent.java b/android/src/main/java/com/dylanvann/fastimage/events/FastImageProgressEvent.java new file mode 100644 index 0000000..c579a95 --- /dev/null +++ b/android/src/main/java/com/dylanvann/fastimage/events/FastImageProgressEvent.java @@ -0,0 +1,34 @@ +package com.dylanvann.fastimage.events; + +import androidx.annotation.NonNull; + +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.uimanager.events.Event; + +public class FastImageProgressEvent extends Event { + + private final int mBytesRead; + private final int mExpectedLength; + + public FastImageProgressEvent(int surfaceId, int viewTag, int bytesRead, int expectedLength) { + super(surfaceId, viewTag); + this.mBytesRead = bytesRead; + this.mExpectedLength = expectedLength; + } + + @NonNull + @Override + public String getEventName() { + return "onFastImageProgress"; + } + + @Override + protected WritableMap getEventData() { + WritableMap eventData = Arguments.createMap(); + eventData.putInt("loaded", mBytesRead); + eventData.putInt("total", mExpectedLength); + return eventData; + } + +} From 9013147fa240307cc45e82a3817711fa61939bc4 Mon Sep 17 00:00:00 2001 From: "Deepanshu.shukla" Date: Fri, 2 Aug 2024 16:28:31 +0530 Subject: [PATCH 2/2] refactor: remove logs --- ReactNativeFastImageExample/src/index.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/ReactNativeFastImageExample/src/index.tsx b/ReactNativeFastImageExample/src/index.tsx index 38d2aac..690ece7 100644 --- a/ReactNativeFastImageExample/src/index.tsx +++ b/ReactNativeFastImageExample/src/index.tsx @@ -13,9 +13,6 @@ LogBox.ignoreLogs([ 'Warning: isMounted(...) is deprecated', 'Module RCTImageLoader', ]); -const uiManager = global?.nativeFabricUIManager ? 'Fabric' : 'Paper'; - -console.log('Running on',uiManager) export default function App() { return (