import React from 'react' ; import { StyleSheet , View , TouchableOpacity , UIManager , findNodeHandle } from 'react-native' ; import { RNIContextMenuButton , RNIContextMenuButtonBaseProps , RNIContextMenuButtonCommands } from '../../native_components/RNIContextMenuButton' ; import type { OnMenuWillShowEvent , OnMenuWillHideEvent , OnMenuDidShowEvent , OnMenuDidHideEvent , OnMenuWillCancelEvent , OnMenuDidCancelEvent , OnPressMenuItemEvent } from '../../types/MenuEvents' ; import type { ContextMenuButtonProps , ContextMenuButtonState } from './ContextMenuButtonTypes' ; import { ActionSheetFallback } from '../../functions/ActionSheetFallback' ; import { ContextMenuView } from '../ContextMenuView' ; import { ContextMenuButtonContext } from '../../context/ContextMenuButtonContext' ; import { LIB_ENV , IS_PLATFORM_IOS } from '../../constants/LibEnv' ; export class ContextMenuButton extends React . PureComponent < ContextMenuButtonProps , ContextMenuButtonState > { nativeRef ! : React . Component ; constructor ( props ) { super ( props ) ; this . state = { menuVisible : false , } ; } ; getProps = ( ) => { const { menuConfig , enableContextMenu , isMenuPrimaryAction , useActionSheetFallback , onMenuWillShow , onMenuWillHide , onMenuWillCancel , onMenuDidShow , onMenuDidHide , onMenuDidCancel , onPressMenuItem , ... viewProps } = this . props ; return { enableContextMenu : ( enableContextMenu ?? true ) , useActionSheetFallback : ( useActionSheetFallback ?? ! LIB_ENV . isContextMenuViewSupported ) , menuConfig , isMenuPrimaryAction , onMenuWillShow , onMenuWillHide , onMenuWillCancel , onMenuDidShow , onMenuDidHide , onMenuDidCancel , onPressMenuItem , viewProps } ; } ; dismissMenu = ( ) => { if ( ! LIB_ENV . isContextMenuButtonSupported ) return ; UIManager . dispatchViewManagerCommand ( findNodeHandle ( this . nativeRef ) , RNIContextMenuButtonCommands . dismissMenu , [ ] ) ; } ; _handleGetRefToContextMenuButton = ( ) => { return this ; } ; _handleOnLongPress = async ( ) => { const props = this . props ; if ( props . menuConfig == null ) return ; const selectedItem = await ActionSheetFallback . show ( props . menuConfig ) ; if ( selectedItem == null ) { props . onMenuDidCancel ?. ( { isUsingActionSheetFallback : true } ) ; } else { props . onPressMenuItem ?. ( { isUsingActionSheetFallback : true , nativeEvent : { ... selectedItem , } } ) ; } ; } ; _handleOnMenuWillShow : OnMenuWillShowEvent = ( event ) => { this . props . onMenuWillShow ?. ( event ) ; event . stopPropagation ( ) ; this . setState ( { menuVisible : true } ) ; } ; _handleOnMenuWillHide : OnMenuWillHideEvent = ( event ) => { this . props . onMenuWillHide ?. ( event ) ; event . stopPropagation ( ) ; this . setState ( { menuVisible : false } ) ; } ; _handleOnMenuWillCancel : OnMenuWillCancelEvent = ( event ) => { this . props . onMenuWillCancel ?. ( event ) ; event . stopPropagation ( ) ; } ; _handleOnMenuDidShow : OnMenuDidShowEvent = ( event ) => { this . props . onMenuDidShow ?. ( event ) ; event . stopPropagation ( ) ; } ; _handleOnMenuDidHide : OnMenuDidHideEvent = ( event ) => { this . props . onMenuDidHide ?. ( event ) ; event . stopPropagation ( ) ; } ; _handleOnMenuDidCancel : OnMenuDidCancelEvent = ( event ) => { this . props . onMenuDidCancel ?. ( event ) ; if ( event . isUsingActionSheetFallback ) return ; event . stopPropagation ( ) ; } ; _handleOnPressMenuItem : OnPressMenuItemEvent = ( event ) => { this . props . onPressMenuItem ?. ( event ) ; if ( event . isUsingActionSheetFallback ) return ; event . stopPropagation ( ) ; } ; render ( ) { const props = this . getProps ( ) ; const state = this . state ; const shouldUseContextMenuButton = ( ! props . useActionSheetFallback && LIB_ENV . isContextMenuButtonSupported ) ; const shouldUseContextMenuView = ( ! props . useActionSheetFallback && ! LIB_ENV . isContextMenuButtonSupported && LIB_ENV . isContextMenuViewSupported ) ; const shouldUseActionSheetFallback = ( IS_PLATFORM_IOS && props . useActionSheetFallback ) ; const nativeComponentProps = { menuConfig : props . menuConfig , enableContextMenu : props . enableContextMenu , isMenuPrimaryAction : props . isMenuPrimaryAction , onMenuWillShow : this . _handleOnMenuWillShow , onMenuWillHide : this . _handleOnMenuWillHide , onMenuDidShow : this . _handleOnMenuDidShow , onMenuDidHide : this . _handleOnMenuDidHide , onMenuDidCancel : this . _handleOnMenuDidCancel , onMenuWillCancel : this . _handleOnMenuWillCancel , onPressMenuItem : this . _handleOnPressMenuItem , } ; const contents = ( shouldUseContextMenuButton ? ( < RNIContextMenuButton { ... props . viewProps } { ... nativeComponentProps } ref = { r => { this . nativeRef = r ! ; } } style = { [ styles . menuButton , props . viewProps . style ] } > { props . viewProps . children } < /RNIContextMenuButton>) : shouldUseContextMenuView ? ( < ContextMenuView { ... props . viewProps } { ... nativeComponentProps } > { props . viewProps . children } < /ContextMenuView>) : shouldUseActionSheetFallback ? ( < TouchableOpacity onLongPress = { this . _handleOnLongPress } activeOpacity = { 0.8 } { ... props . viewProps } > { this . props . children } < /TouchableOpacity>) : ( < View { ... props . viewProps } > { this . props . children } < /View>)); return ( < ContextMenuButtonContext . Provider value = { { getRefToContextMenuButton : this . _handleGetRefToContextMenuButton , isMenuVisible : state . menuVisible , } } > { contents } < /ContextMenuButtonContext.Provider>); } ; } ; const styles = StyleSheet . create ( { menuButton : { backgroundColor : 'transparent' , } , } ) ;