mpiannucci / react-native-context-menu-view

Use native context menus in React Native
MIT License
676 stars 69 forks source link

Prevent action on react native buttons while context menu is presented and support adding a title to Android context menu #120

Open jefflewis opened 5 months ago

jefflewis commented 5 months ago

Hi! 👋

Firstly, thanks for your work on this project! 🙂

Today I used patch-package to patch react-native-context-menu-view@1.15.0 for the project I'm working on.

Here is the diff that solved my problem:

diff --git a/node_modules/react-native-context-menu-view/android/src/main/java/com/mpiannucci/reactnativecontextmenu/ContextMenuManager.java b/node_modules/react-native-context-menu-view/android/src/main/java/com/mpiannucci/reactnativecontextmenu/ContextMenuManager.java
index 403dac6..52a0c2f 100644
--- a/node_modules/react-native-context-menu-view/android/src/main/java/com/mpiannucci/reactnativecontextmenu/ContextMenuManager.java
+++ b/node_modules/react-native-context-menu-view/android/src/main/java/com/mpiannucci/reactnativecontextmenu/ContextMenuManager.java
@@ -31,9 +31,7 @@ public class ContextMenuManager extends ViewGroupManager<ContextMenuView> {
     }

     @ReactProp(name = "title")
-    public void setTitle(ContextMenuView view, @Nullable String title) {
-        // TODO: Maybe support this? IDK if its necessary though
-    }
+    public void setTitle(ContextMenuView view, @Nullable String title) { view.setTitle(title); }

     @ReactProp(name = "actions")
     public void setActions(ContextMenuView view, @Nullable ReadableArray actions) {
diff --git a/node_modules/react-native-context-menu-view/android/src/main/java/com/mpiannucci/reactnativecontextmenu/ContextMenuView.java b/node_modules/react-native-context-menu-view/android/src/main/java/com/mpiannucci/reactnativecontextmenu/ContextMenuView.java
index 9fc8eeb..69bb41e 100644
--- a/node_modules/react-native-context-menu-view/android/src/main/java/com/mpiannucci/reactnativecontextmenu/ContextMenuView.java
+++ b/node_modules/react-native-context-menu-view/android/src/main/java/com/mpiannucci/reactnativecontextmenu/ContextMenuView.java
@@ -34,6 +34,7 @@ import javax.annotation.Nullable;

 public class ContextMenuView extends ReactViewGroup implements View.OnCreateContextMenuListener {
     @Nullable ReadableArray actions;
+    @Nullable String title;

     boolean cancelled = true;

@@ -92,6 +93,7 @@ public class ContextMenuView extends ReactViewGroup implements View.OnCreateCont
     public void onCreateContextMenu(ContextMenu contextMenu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) {
         contextMenu.clear();
         setMenuIconDisplay(contextMenu, true);
+        contextMenu.setHeaderTitle(title);

         for (int i = 0; i < actions.size(); i++) {
             ReadableMap action = actions.getMap(i);
@@ -111,6 +113,10 @@ public class ContextMenuView extends ReactViewGroup implements View.OnCreateCont
         this.actions = actions;
     }

+    public void setTitle(@Nullable String title) {
+        this.title = title;
+    }
+
     public void setDropdownMenuMode(@Nullable boolean enabled) {
         this.dropdownMenuMode = enabled;
     }
diff --git a/node_modules/react-native-context-menu-view/ios/ContextMenuView.m b/node_modules/react-native-context-menu-view/ios/ContextMenuView.m
index 7f8ee75..5531995 100644
--- a/node_modules/react-native-context-menu-view/ios/ContextMenuView.m
+++ b/node_modules/react-native-context-menu-view/ios/ContextMenuView.m
@@ -18,6 +18,7 @@
 @implementation ContextMenuView {
   BOOL _cancelled;
   UIView *_customView;
+  UIView *_bgView;
 }

 - (id) init {
@@ -90,6 +91,15 @@
 }

 - (void)contextMenuInteraction:(UIContextMenuInteraction *)interaction willDisplayMenuForConfiguration:(UIContextMenuConfiguration *)configuration animator:(id<UIContextMenuInteractionAnimating>)animator API_AVAILABLE(ios(13.0)) {
+  // Add a transparent view to the root view that will intercept touch events.
+  // This will prevent buttons in React views from being actionable while the
+  // context menu is displayed.
+  _bgView = [[UIView alloc] init];
+  _bgView.backgroundColor = UIColor.clearColor;
+  _bgView.userInteractionEnabled = YES;
+  _bgView.frame = self.reactViewController.view.bounds;
+  [self.reactViewController.view addSubview: _bgView];
+  
   _cancelled = true;
 }

@@ -103,6 +113,7 @@
   if (_cancelled && self.onCancel) {
     self.onCancel(@{});
   }
+  [self.reactViewController.view removeReactSubview:_bgView];
 }

 - (UITargetedPreview *)contextMenuInteraction:(UIContextMenuInteraction *)interaction previewForHighlightingMenuWithConfiguration:(UIContextMenuConfiguration *)configuration API_AVAILABLE(ios(13.0)) {

This issue body was partially generated by patch-package.

mpiannucci commented 5 months ago

This is really cool! Would you be up for opening a PR to add this in? Thanks in advance

jefflewis commented 5 months ago

I'm adding this to our own app, which will go through a thorough set of regression tests. Once that is all done and the patch is proven, I'll add a PR here with whatever we end up with.

I think everything is OK with this. I'm not doin null checking on the view, but my assumption is that the willEndForConfiguration will always be called if willDisplayMenuForConfiguration is called. If that isn't true, this would leave that garbage view in place forever.

For the android title, I'll split into a separate PR... mostly because the view doesn't expand to fit the title... I just put a bunch of spaces in the one spot where this affected my app, but it'd be better to get an actual fix in place.

mabdurrafey-afl commented 4 months ago

@jefflewis The patch for prevention of action while context menu is appearing is not working on our side.

jefflewis commented 2 months ago

@jefflewis The patch for prevention of action while context menu is appearing is not working on our side.

I'll ensure I add to the sample app to test this behavior. This so far has been working for us the past month in production.