Skip to content

Commit

Permalink
🐞 Fix: ContextMenuView.onPressMenuItem
Browse files Browse the repository at this point in the history
Summary: Wait for context menu to close before firing `onPressMenuItem`.
* Fix for issue #43
  • Loading branch information
dominicstop committed Jun 17, 2022
1 parent a1d1314 commit 9a1d224
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 5 deletions.
45 changes: 41 additions & 4 deletions src/components/ContextMenuView/ContextMenuView.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React from 'react';
import { StyleSheet, View, TouchableOpacity } from 'react-native';

import { TSEventEmitter } from '@dominicstop/ts-event-emitter';

import { RNIContextMenuView } from '../../native_components/RNIContextMenuView';
import { RNIWrapperView } from '../../native_components/RNIWrapperView';

Expand All @@ -9,7 +11,7 @@ import { RNIContextMenuViewModule } from '../../native_modules/RNIContextMenuVie
import { ContextMenuViewContext } from '../../context/ContextMenuViewContext';

import type { OnMenuWillShowEvent, OnMenuWillHideEvent, OnMenuDidShowEvent, OnMenuDidHideEvent, OnMenuWillCancelEvent, OnMenuDidCancelEvent, OnMenuWillCreateEvent, OnPressMenuItemEvent, OnPressMenuPreviewEvent, OnMenuAuxiliaryPreviewWillShowEvent, OnMenuAuxiliaryPreviewDidShowEvent } from '../../types/MenuEvents';
import type { ContextMenuViewProps, ContextMenuViewState } from './ContextMenuViewTypes';
import type { ContextMenuViewProps, ContextMenuViewState, NavigatorViewEventEmitter } from './ContextMenuViewTypes';

// @ts-ignore - TODO
import { ActionSheetFallback } from '../../functions/ActionSheetFallback';
Expand All @@ -32,13 +34,17 @@ export class ContextMenuView extends

nativeRef!: React.Component;

emitter: NavigatorViewEventEmitter;

constructor(props: ContextMenuViewProps){
super(props);

this.state = {
menuVisible : false,
mountPreview: false,
};

this.emitter = new TSEventEmitter();
};

private getProps = () => {
Expand All @@ -48,6 +54,7 @@ export class ContextMenuView extends
previewConfig,
auxiliaryPreviewConfig,
shouldUseDiscoverabilityTitleAsFallbackValueForSubtitle,
shouldWaitForMenuToHideBeforeFiringOnPressMenuItem,
// event props
onMenuWillShow,
onMenuWillHide,
Expand Down Expand Up @@ -76,6 +83,9 @@ export class ContextMenuView extends
shouldUseDiscoverabilityTitleAsFallbackValueForSubtitle: (
shouldUseDiscoverabilityTitleAsFallbackValueForSubtitle ?? true
),
shouldWaitForMenuToHideBeforeFiringOnPressMenuItem: (
shouldWaitForMenuToHideBeforeFiringOnPressMenuItem ?? true
),

// B. Pass down props...
menuConfig,
Expand Down Expand Up @@ -172,7 +182,10 @@ export class ContextMenuView extends

private _handleOnMenuDidHide: OnMenuDidHideEvent = (event) => {
this.props.onMenuDidHide?.(event);
this.emitter.emit('onMenuDidHide', event);

event.stopPropagation();
event.persist();
};

private _handleOnMenuDidCancel: OnMenuDidCancelEvent = (event) => {
Expand All @@ -193,12 +206,36 @@ export class ContextMenuView extends
event.stopPropagation();
};

private _handleOnPressMenuItem: OnPressMenuItemEvent = (event) => {
this.props.onPressMenuItem?.(event);

private _handleOnPressMenuItem: OnPressMenuItemEvent = async (event) => {
const props = this.getProps();
// guard: event is a native event
if(event.isUsingActionSheetFallback) return;

event.stopPropagation();
event.persist();

try {
if(props.shouldWaitForMenuToHideBeforeFiringOnPressMenuItem){
// wait for `onMenuDidHide`
await Helpers.promiseWithTimeout(1000, new Promise<void>((resolve) => {
this.emitter.once('onMenuDidHide', () => {
resolve();
});
}));

props.onPressMenuItem?.(event);

} else {
props.onPressMenuItem?.(event);
};

} catch(error){
console.error(
'_handleOnPressMenuItem - Promise waiting for `onMenuDidHide`'
+ ' has timed out'
);
};
};

private _handleOnPressMenuPreview: OnPressMenuPreviewEvent = (event) => {
Expand Down
19 changes: 18 additions & 1 deletion src/components/ContextMenuView/ContextMenuViewTypes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import type React from 'react';

import type { TSEventEmitter } from '@dominicstop/ts-event-emitter';

import type { ViewProps } from 'react-native';
import type { OnMenuDidHideEventObject } from 'src/types/MenuEvents';
import type { KeyMapType } from 'src/types/UtilityTypes';

import type { RNIContextMenuViewProps } from '../../native_components/RNIContextMenuView';

Expand Down Expand Up @@ -27,6 +32,7 @@ export type ContextMenuViewBaseProps = Pick<RNIContextMenuViewProps,
> & {
lazyPreview?: boolean;
useActionSheetFallback?: boolean;
shouldWaitForMenuToHideBeforeFiringOnPressMenuItem?: boolean;

renderPreview?: RenderItem;
renderAuxillaryPreview?: RenderItem;
Expand All @@ -38,4 +44,15 @@ export type ContextMenuViewProps =
export type ContextMenuViewState = {
menuVisible: boolean;
mountPreview: boolean;
};
};

export enum ContextMenuEmitterEvents {
onMenuDidHide = "onMenuDidHide",
};

export type ContextMenuEmitterEventMap = KeyMapType<ContextMenuEmitterEvents, {
onMenuDidHide: OnMenuDidHideEventObject['nativeEvent'],
}>

export type NavigatorViewEventEmitter =
TSEventEmitter<ContextMenuEmitterEvents, ContextMenuEmitterEventMap>;

0 comments on commit 9a1d224

Please sign in to comment.