From 052d63681a6f594b1b072e86b920882bc5a6c763 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Fri, 15 Mar 2024 16:52:02 +0000 Subject: [PATCH] [Android] Add support for Bridgeless Mode - 0.74 --- .../fastimage/FastImageRequestListener.java | 33 +++++++++++++----- .../fastimage/FastImageViewManager.java | 25 +++++++++----- .../fastimage/FastImageViewWithUrl.java | 33 ++++++++++-------- .../fastimage/events/FastImageErrorEvent.java | 34 +++++++++++++++++++ .../events/FastImageLoadEndEvent.java | 19 +++++++++++ .../fastimage/events/FastImageLoadEvent.java | 19 +++++++++++ .../events/FastImageLoadStartEvent.java | 19 +++++++++++ .../events/FastImageProgressEvent.java | 34 +++++++++++++++++++ 8 files changed, 185 insertions(+), 31 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/android/src/main/java/com/dylanvann/fastimage/FastImageRequestListener.java b/android/src/main/java/com/dylanvann/fastimage/FastImageRequestListener.java index dbeb81313..42ce0f0bc 100644 --- a/android/src/main/java/com/dylanvann/fastimage/FastImageRequestListener.java +++ b/android/src/main/java/com/dylanvann/fastimage/FastImageRequestListener.java @@ -7,10 +7,15 @@ import com.bumptech.glide.request.RequestListener; import com.bumptech.glide.request.target.ImageViewTarget; import com.bumptech.glide.request.target.Target; +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.WritableMap; 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,15 @@ 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 +61,15 @@ 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 c7a795471..964a7ce4f 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.annotations.ReactProp; -import com.facebook.react.uimanager.events.RCTEventEmitter; +import com.facebook.react.uimanager.common.ViewUtil; +import com.facebook.react.uimanager.events.EventDispatcher; 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 34fcf898d..c45b628b0 100644 --- a/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java +++ b/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java @@ -13,11 +13,12 @@ import com.bumptech.glide.RequestManager; import com.bumptech.glide.load.model.GlideUrl; import com.bumptech.glide.request.Request; +import com.dylanvann.fastimage.events.FastImageErrorEvent; +import com.dylanvann.fastimage.events.FastImageLoadStartEvent; import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.WritableMap; -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; import java.util.ArrayList; import java.util.Collections; @@ -81,11 +82,14 @@ 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); @@ -120,13 +124,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 000000000..a3afa5b70 --- /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 000000000..e85efb33b --- /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 000000000..c29037d4d --- /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 000000000..2dca758d7 --- /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 000000000..6f7f11c86 --- /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; + } + +}