Skip to content

Commit

Permalink
feat: make pointer events work on both platforms (#1879)
Browse files Browse the repository at this point in the history
PR adding proper handling of pointerEvents in the library. Based on the comment by @RSNara :

> For all Android components, static ViewConfigs are generated from the components types + BaseVIewConfig.android.js. The BaseViewConfig for all android components is facebook/react-native@c5217f1/Libraries/NativeComponent/BaseViewConfig.android.js#L288-L297, which doesn't contain the pointerEvents validAttribute. So, React Native SVG components must re-declare the pointerEvents validAttribute. Otherwise, the pointerEvents validAttribute won't be in the static ViewConfig, which means React won't pass that prop to native with Static ViewConfigs.

We needed a way to trick codegen since we added our own pointerEvents with string type, and such prop is already present in ViewProps from react-native, but as a union of strings, so their types did not match. As codegen parses string literals, we include changed ViewProps type, without pointerEvents prop, so we satisfy both codegen and TS.

As for how pointerEvents are handled now:

iOS:
Paper: prop is passed in RCTViewManager but it looks like it does not matter what you pass there, since even if you set none, resulting in view.userInteractionEnabled = NO; (facebook/react-native@065db68/React/Views/RCTViewManager.m#L256), custom implementation of hitTest will not take it into account anyhow.

Fabric: we don’t use pointerEvents prop but it is not a problem since it is not used in the implementation of neither SvgView and RCTViewComponentView (it is used in hitTest method there, but we override it)

Android:
Paper: the prop was passed through ReactViewManager and was set on the view directly. But the setter for pointerEvents is not visible outside of ReactViewGroup . After adding Fabric integration for both platforms: BaseViewManager does not implement setter for pointerEvents so we have to add the prop by ourselves. Still, we cannot call the setter from ReactViewGroup since it is not visible, so all the logic for pointerEvents should be migrated to SvgView unfortunately or we should use reflection to get that method.

Despite that, it seems that behavior differs on Android and iOS since setting pointerEvents to none on Android makes the view not clickable, whereas on iOS it does not change anything.
  • Loading branch information
WoLewicki authored Sep 30, 2022
1 parent f734301 commit 1beacf1
Show file tree
Hide file tree
Showing 69 changed files with 186 additions and 62 deletions.
6 changes: 2 additions & 4 deletions .github/workflows/ios-build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,8 @@ jobs:
- name: Restore build artifacts from cache
uses: actions/cache@v3
with:
path: |
${{ matrix.working-directory }}/ios/build
~/Library/Developer/Xcode/DerivedData
key: ${{ runner.os }}-ios-build-${{ matrix.working-directory }}-${{ hashFiles(format('{0}/ios/Podfile.lock', matrix.working-directory)) }}
path: ~/Library/Developer/Xcode/DerivedData
key: ${{ runner.os }}-ios-derived-data-${{ matrix.working-directory }}-${{ hashFiles(format('{0}/ios/Podfile.lock', matrix.working-directory)) }}

- name: Build app
working-directory: ${{ matrix.working-directory }}
Expand Down
8 changes: 4 additions & 4 deletions Example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ PODS:
- React-jsi (= 0.70.0)
- React-logger (= 0.70.0)
- React-perflogger (= 0.70.0)
- RNSVG (13.1.0):
- RNSVG (13.2.0):
- React-Core
- SocketRocket (0.6.0)
- Yoga (1.14.0)
Expand Down Expand Up @@ -530,7 +530,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
boost: a7c83b31436843459a1961bfd74b96033dc77234
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662
FBLazyVector: 6c76fe46345039d5cf0549e9ddaf5aa169630a4a
FBReactNativeSpec: 1a270246542f5c52248cb26a96db119cfe3cb760
Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0
Expand All @@ -543,7 +543,7 @@ SPEC CHECKSUMS:
Flipper-RSocket: d9d9ade67cbecf6ac10730304bf5607266dd2541
FlipperKit: cbdee19bdd4e7f05472a66ce290f1b729ba3cb86
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
glog: 476ee3e89abb49e07f822b48323c51c57124b572
hermes-engine: 8e84f1284180801c1a1b241f443ba64f931ff561
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
Expand Down Expand Up @@ -574,7 +574,7 @@ SPEC CHECKSUMS:
React-RCTVibration: 5499b77c0fd57f346a5f0b36bb79fdb020d17d3e
React-runtimeexecutor: 80c195ffcafb190f531fdc849dc2d19cb4bb2b34
ReactCommon: de55f940495d7bf87b5d7bf55b5b15cdd50d7d7b
RNSVG: 1153e8eeb34c788841016c517dba9f57f20b762f
RNSVG: 07037623c36f12e41312730622d5f6b3656227ca
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
Yoga: 82c9e8f652789f67d98bed5aef9d6653f71b04a9
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
Expand Down
4 changes: 2 additions & 2 deletions FabricExample/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,7 @@ PODS:
- React-jsi (= 0.70.0)
- React-logger (= 0.70.0)
- React-perflogger (= 0.70.0)
- RNSVG (13.1.0):
- RNSVG (13.2.0):
- RCT-Folly
- RCTRequired
- RCTTypeSafety
Expand Down Expand Up @@ -927,7 +927,7 @@ SPEC CHECKSUMS:
React-rncore: 8858fe6b719170c20c197a8fd2dd53507bdae04b
React-runtimeexecutor: 80c195ffcafb190f531fdc849dc2d19cb4bb2b34
ReactCommon: de55f940495d7bf87b5d7bf55b5b15cdd50d7d7b
RNSVG: 81cdb77109d5f3e77dcf1dd8045aaaa8144afddf
RNSVG: fa7f6f437c90eea1fbc3d142a40365d561824ab3
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
Yoga: 82c9e8f652789f67d98bed5aef9d6653f71b04a9
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
Expand Down
18 changes: 18 additions & 0 deletions android/src/main/java/com/horcrux/svg/SvgViewManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@

import android.util.SparseArray;
import com.facebook.react.bridge.Dynamic;
import com.facebook.react.uimanager.PointerEvents;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewManagerDelegate;
import com.facebook.react.uimanager.ViewProps;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.viewmanagers.RNSVGSvgViewManagerDelegate;
import com.facebook.react.viewmanagers.RNSVGSvgViewManagerInterface;
import com.facebook.react.views.view.ReactViewGroup;
import com.facebook.react.views.view.ReactViewManager;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

Expand Down Expand Up @@ -162,4 +166,18 @@ public void setBbHeight(SvgView view, @Nullable String value) {
public void setBbHeight(SvgView view, @Nullable Double value) {
view.setBbHeight(value);
}

@ReactProp(name = ViewProps.POINTER_EVENTS)
public void setPointerEvents(SvgView view, @Nullable String pointerEventsStr) {
try {
Class<?> superclass = view.getClass().getSuperclass();
if (superclass != null) {
Method method = superclass.getDeclaredMethod("setPointerEvents", PointerEvents.class);
method.setAccessible(true);
method.invoke(view, PointerEvents.parsePointerEvents(pointerEventsStr));
}
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "display":
mViewManager.setDisplay(view, value == null ? null : (String) value);
break;
case "pointerEvents":
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
break;
case "fill":
mViewManager.setFill(view, (ReadableMap) value);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public interface RNSVGCircleManagerInterface<T extends View> {
void setClipRule(T view, int value);
void setResponsible(T view, boolean value);
void setDisplay(T view, @Nullable String value);
void setPointerEvents(T view, @Nullable String value);
void setFill(T view, @Nullable ReadableMap value);
void setFillOpacity(T view, float value);
void setFillRule(T view, int value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "display":
mViewManager.setDisplay(view, value == null ? null : (String) value);
break;
case "pointerEvents":
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
break;
case "fill":
mViewManager.setFill(view, (ReadableMap) value);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public interface RNSVGClipPathManagerInterface<T extends View> {
void setClipRule(T view, int value);
void setResponsible(T view, boolean value);
void setDisplay(T view, @Nullable String value);
void setPointerEvents(T view, @Nullable String value);
void setFill(T view, @Nullable ReadableMap value);
void setFillOpacity(T view, float value);
void setFillRule(T view, int value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "display":
mViewManager.setDisplay(view, value == null ? null : (String) value);
break;
case "pointerEvents":
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
break;
default:
super.setProperty(view, propName, value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ public interface RNSVGDefsManagerInterface<T extends View> {
void setClipRule(T view, int value);
void setResponsible(T view, boolean value);
void setDisplay(T view, @Nullable String value);
void setPointerEvents(T view, @Nullable String value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "display":
mViewManager.setDisplay(view, value == null ? null : (String) value);
break;
case "pointerEvents":
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
break;
case "fill":
mViewManager.setFill(view, (ReadableMap) value);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public interface RNSVGEllipseManagerInterface<T extends View> {
void setClipRule(T view, int value);
void setResponsible(T view, boolean value);
void setDisplay(T view, @Nullable String value);
void setPointerEvents(T view, @Nullable String value);
void setFill(T view, @Nullable ReadableMap value);
void setFillOpacity(T view, float value);
void setFillRule(T view, int value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "display":
mViewManager.setDisplay(view, value == null ? null : (String) value);
break;
case "pointerEvents":
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
break;
case "fill":
mViewManager.setFill(view, (ReadableMap) value);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public interface RNSVGForeignObjectManagerInterface<T extends View> {
void setClipRule(T view, int value);
void setResponsible(T view, boolean value);
void setDisplay(T view, @Nullable String value);
void setPointerEvents(T view, @Nullable String value);
void setFill(T view, @Nullable ReadableMap value);
void setFillOpacity(T view, float value);
void setFillRule(T view, int value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "display":
mViewManager.setDisplay(view, value == null ? null : (String) value);
break;
case "pointerEvents":
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
break;
case "fill":
mViewManager.setFill(view, (ReadableMap) value);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public interface RNSVGGroupManagerInterface<T extends View> {
void setClipRule(T view, int value);
void setResponsible(T view, boolean value);
void setDisplay(T view, @Nullable String value);
void setPointerEvents(T view, @Nullable String value);
void setFill(T view, @Nullable ReadableMap value);
void setFillOpacity(T view, float value);
void setFillRule(T view, int value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "display":
mViewManager.setDisplay(view, value == null ? null : (String) value);
break;
case "pointerEvents":
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
break;
case "fill":
mViewManager.setFill(view, (ReadableMap) value);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public interface RNSVGImageManagerInterface<T extends View> {
void setClipRule(T view, int value);
void setResponsible(T view, boolean value);
void setDisplay(T view, @Nullable String value);
void setPointerEvents(T view, @Nullable String value);
void setFill(T view, @Nullable ReadableMap value);
void setFillOpacity(T view, float value);
void setFillRule(T view, int value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "display":
mViewManager.setDisplay(view, value == null ? null : (String) value);
break;
case "pointerEvents":
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
break;
case "fill":
mViewManager.setFill(view, (ReadableMap) value);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public interface RNSVGLineManagerInterface<T extends View> {
void setClipRule(T view, int value);
void setResponsible(T view, boolean value);
void setDisplay(T view, @Nullable String value);
void setPointerEvents(T view, @Nullable String value);
void setFill(T view, @Nullable ReadableMap value);
void setFillOpacity(T view, float value);
void setFillRule(T view, int value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "display":
mViewManager.setDisplay(view, value == null ? null : (String) value);
break;
case "pointerEvents":
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
break;
case "x1":
if (value instanceof String) {
mViewManager.setX1(view, (String) value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public interface RNSVGLinearGradientManagerInterface<T extends View> {
void setClipRule(T view, int value);
void setResponsible(T view, boolean value);
void setDisplay(T view, @Nullable String value);
void setPointerEvents(T view, @Nullable String value);
void setX1(T view, @Nullable String value);
void setX1(T view, @Nullable Double value);
void setY1(T view, @Nullable String value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "display":
mViewManager.setDisplay(view, value == null ? null : (String) value);
break;
case "pointerEvents":
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
break;
case "fill":
mViewManager.setFill(view, (ReadableMap) value);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public interface RNSVGMarkerManagerInterface<T extends View> {
void setClipRule(T view, int value);
void setResponsible(T view, boolean value);
void setDisplay(T view, @Nullable String value);
void setPointerEvents(T view, @Nullable String value);
void setFill(T view, @Nullable ReadableMap value);
void setFillOpacity(T view, float value);
void setFillRule(T view, int value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "display":
mViewManager.setDisplay(view, value == null ? null : (String) value);
break;
case "pointerEvents":
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
break;
case "fill":
mViewManager.setFill(view, (ReadableMap) value);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public interface RNSVGMaskManagerInterface<T extends View> {
void setClipRule(T view, int value);
void setResponsible(T view, boolean value);
void setDisplay(T view, @Nullable String value);
void setPointerEvents(T view, @Nullable String value);
void setFill(T view, @Nullable ReadableMap value);
void setFillOpacity(T view, float value);
void setFillRule(T view, int value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "display":
mViewManager.setDisplay(view, value == null ? null : (String) value);
break;
case "pointerEvents":
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
break;
case "fill":
mViewManager.setFill(view, (ReadableMap) value);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public interface RNSVGPathManagerInterface<T extends View> {
void setClipRule(T view, int value);
void setResponsible(T view, boolean value);
void setDisplay(T view, @Nullable String value);
void setPointerEvents(T view, @Nullable String value);
void setFill(T view, @Nullable ReadableMap value);
void setFillOpacity(T view, float value);
void setFillRule(T view, int value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "display":
mViewManager.setDisplay(view, value == null ? null : (String) value);
break;
case "pointerEvents":
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
break;
case "fill":
mViewManager.setFill(view, (ReadableMap) value);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public interface RNSVGPatternManagerInterface<T extends View> {
void setClipRule(T view, int value);
void setResponsible(T view, boolean value);
void setDisplay(T view, @Nullable String value);
void setPointerEvents(T view, @Nullable String value);
void setFill(T view, @Nullable ReadableMap value);
void setFillOpacity(T view, float value);
void setFillRule(T view, int value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "display":
mViewManager.setDisplay(view, value == null ? null : (String) value);
break;
case "pointerEvents":
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
break;
case "fx":
if (value instanceof String) {
mViewManager.setFx(view, (String) value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public interface RNSVGRadialGradientManagerInterface<T extends View> {
void setClipRule(T view, int value);
void setResponsible(T view, boolean value);
void setDisplay(T view, @Nullable String value);
void setPointerEvents(T view, @Nullable String value);
void setFx(T view, @Nullable String value);
void setFx(T view, @Nullable Double value);
void setFy(T view, @Nullable String value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "display":
mViewManager.setDisplay(view, value == null ? null : (String) value);
break;
case "pointerEvents":
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
break;
case "fill":
mViewManager.setFill(view, (ReadableMap) value);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public interface RNSVGRectManagerInterface<T extends View> {
void setClipRule(T view, int value);
void setResponsible(T view, boolean value);
void setDisplay(T view, @Nullable String value);
void setPointerEvents(T view, @Nullable String value);
void setFill(T view, @Nullable ReadableMap value);
void setFillOpacity(T view, float value);
void setFillRule(T view, int value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "color":
mViewManager.setColor(view, ColorPropConverter.getColor(value, view.getContext()));
break;
case "pointerEvents":
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
break;
default:
super.setProperty(view, propName, value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ public interface RNSVGSvgViewManagerInterface<T extends View> {
void setMeetOrSlice(T view, int value);
void setTintColor(T view, @Nullable Integer value);
void setColor(T view, @Nullable Integer value);
void setPointerEvents(T view, @Nullable String value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "display":
mViewManager.setDisplay(view, value == null ? null : (String) value);
break;
case "pointerEvents":
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
break;
case "fill":
mViewManager.setFill(view, (ReadableMap) value);
break;
Expand Down
Loading

0 comments on commit 1beacf1

Please sign in to comment.