Impl. ContextMenu Events

This commit is contained in:
Dominic Go 2020-10-24 23:16:33 +08:00
parent 53dde7b48d
commit c69530abbd
3 changed files with 120 additions and 13 deletions

View File

@ -11,11 +11,18 @@
@interface RCT_EXTERN_MODULE(RCTContextMenuManager, RCTViewManager)
// --------------------------------
// MARK: Props - RN Component Props
// --------------------------------
// -----------------------------------
// MARK: Props - RN Comp Props: Events
// -----------------------------------
RCT_EXPORT_VIEW_PROPERTY(onPressMenuItem, RCTDirectEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onMenuShow , RCTBubblingEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onMenuHide , RCTBubblingEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onPressMenuItem , RCTBubblingEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onPressMenuPreview, RCTBubblingEventBlock);
// -----------------------------------
// MARK: Props - RN Comp Props: Values
// -----------------------------------
RCT_EXPORT_VIEW_PROPERTY(menuConfig, NSDictionary);

View File

@ -12,7 +12,18 @@ import UIKit
@available(iOS 13, *)
class RCTContextMenuView: UIView {
@objc var onPressMenuItem: RCTDirectEventBlock?;
// ---------------------------------------------
// MARK: RCTContextMenuView - RN Event Callbacks
// ---------------------------------------------
@objc var onMenuShow : RCTBubblingEventBlock?;
@objc var onMenuHide : RCTBubblingEventBlock?;
@objc var onPressMenuItem : RCTBubblingEventBlock?;
@objc var onPressMenuPreview: RCTBubblingEventBlock?;
// -----------------------------------
// MARK: RCTContextMenuView - RN Props
// -----------------------------------
private var _menuConfig: RCTMenuItem?;
@objc var menuConfig: NSDictionary? {
@ -32,6 +43,10 @@ class RCTContextMenuView: UIView {
}
};
// -------------------------------
// MARK: RCTContextMenuView - Init
// -------------------------------
init(bridge: RCTBridge) {
super.init(frame: CGRect());
@ -53,7 +68,10 @@ extension RCTContextMenuView: UIContextMenuInteractionDelegate {
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
guard let menuConfig = self._menuConfig else {
#if DEBUG
print("guard check failed - contextMenuInteraction, menuConfig: is nil");
print("RCTContextMenuView, UIContextMenuInteractionDelegate"
+ " - contextMenuInteraction: config"
+ " - guard check failed, menuConfig: nil"
);
#endif
return nil;
};
@ -64,4 +82,37 @@ extension RCTContextMenuView: UIContextMenuInteractionDelegate {
});
});
};
// context menu display begins
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willDisplayMenuFor configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionAnimating?) {
#if DEBUG
print("RCTContextMenuView, UIContextMenuInteractionDelegate"
+ " - contextMenuInteraction: will show"
);
#endif
self.onMenuShow?([:]);
};
// context menu display ends
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willEndFor configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionAnimating?) {
#if DEBUG
print("RCTContextMenuView, UIContextMenuInteractionDelegate"
+ " - contextMenuInteraction: will hide"
);
#endif
self.onMenuHide?([:]);
};
// context menu preview tapped
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) {
#if DEBUG
print("RCTContextMenuView, UIContextMenuInteractionDelegate"
+ " - contextMenuInteraction: preview tapped"
);
#endif
self.onPressMenuPreview?([:]);
};
};

View File

@ -8,33 +8,82 @@ const NativeCommands = UIManager[componentName]?.Commands;
const NativeComponent = requireNativeComponent(componentName);
const NATIVE_PROP_KEYS = {
menuConfig : 'menuConfig' ,
onPressMenuItem: 'onPressMenuItem',
// props: values --------
menuConfig: 'menuConfig',
// props: events ------------------------
onMenuShow : 'onMenuShow' ,
onMenuHide : 'onMenuHide' ,
onPressMenuItem : 'onPressMenuItem' ,
onPressMenuPreview: 'onPressMenuPreview',
};
export class ContextMenuView extends React.PureComponent {
static proptypes = {
menuConfig: Proptypes.object,
onPressMenuItem: Proptypes.func,
// events -------------------------
onMenuShow : Proptypes.func,
onMenuHide : Proptypes.func,
onPressMenuItem : Proptypes.func,
onPressMenuPreview: Proptypes.func,
};
constructor(props){
super(props);
this.state = {
menuVisible: false,
};
};
//#region - Event Handlers
_handleOnMenuShow = (event) => {
const { onMenuShow } = this.props;
onMenuShow?.(event);
this.setState({menuVisible: true});
};
_handleOnMenuHide = (event) => {
const { onMenuHide } = this.props;
onMenuHide?.(event);
this.setState({menuVisible: false});
};
_handleOnPressMenuItem = ({nativeEvent}) => {
this.props.onPressMenuItem?.({key: nativeEvent.key});
};
_handleOnPressMenuPreview = (event) => {
const { onPressMenuPreview } = this.props;
onPressMenuPreview?.(event);
};
//#endregion
render(){
const { style, ...props } = this.props;
const { style, children, ...props } = this.props;
const { menuVisible } = this.state;
const nativeProps = {
...props,
style: [styles.menuView, style],
[NATIVE_PROP_KEYS.onPressMenuItem]: this._handleOnPressMenuItem,
// Native Props ------------------------------------------------------
[NATIVE_PROP_KEYS.onMenuShow ]: this._handleOnMenuShow ,
[NATIVE_PROP_KEYS.onMenuHide ]: this._handleOnMenuHide ,
[NATIVE_PROP_KEYS.onPressMenuItem ]: this._handleOnPressMenuItem ,
[NATIVE_PROP_KEYS.onPressMenuPreview]: this._handleOnPressMenuPreview,
};
return(
<NativeComponent
style={[styles.menuView, style]}
{...nativeProps}
/>
>
{React.Children.map(children, child =>
React.cloneElement(child, {menuVisible})
)}
</NativeComponent>
);
};
};