Skip to content

Commit

Permalink
Fix nested pressable's event propagation. (#2981)
Browse files Browse the repository at this point in the history
### Issue:
`Test case`: `3` nested pressables
`Actions`: `click`, `press for <500ms`, `press for >500ms`
`Expected behaviour`: No propagation
`Observed behaviour`: Propagation for `500ms` (until long press
activates), then no propagation.

### Cause:
Touch and non-active events disregard component's layer,
only state respecting component's level is `ACTIVE`.

### Solution:
Create a component which activates immediately after pressing
`Pressable`, capture that event and use it for state setting and
callback calling.

### Important:
This PR also performs a lot of de-cluttering work in the `utils.ts`
file.
This is necessary due to the convoluted nature of the handled problem,
it was especially important to me in this PR to be dealing with clearly
labelled functions.

closes: #2980
  • Loading branch information
latekvo committed Jul 25, 2024
1 parent eb7ae8c commit e2098dc
Show file tree
Hide file tree
Showing 5 changed files with 286 additions and 85 deletions.
5 changes: 5 additions & 0 deletions example/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import NestedFling from './src/release_tests/nestedFling';
import MouseButtons from './src/release_tests/mouseButtons';
import ContextMenu from './src/release_tests/contextMenu';
import NestedTouchables from './src/release_tests/nestedTouchables';
import NestedPressables from './src/release_tests/nestedPressables';
import NestedButtons from './src/release_tests/nestedButtons';
import PointerType from './src/release_tests/pointerType';
import SwipeableReanimation from './src/release_tests/swipeableReanimation';
Expand Down Expand Up @@ -130,6 +131,10 @@ const EXAMPLES: ExamplesSection[] = [
name: 'Nested Touchables - issue #784',
component: NestedTouchables as React.ComponentType,
},
{
name: 'Nested Pressables - issue #2980',
component: NestedPressables as React.ComponentType,
},
{
name: 'Nested buttons (sound & ripple on Android)',
component: NestedButtons,
Expand Down
89 changes: 89 additions & 0 deletions example/src/release_tests/nestedPressables/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React from 'react';
import {
Pressable as LegacyPressable,
PressableStateCallbackType,
StyleProp,
StyleSheet,
Text,
View,
ViewStyle,
} from 'react-native';
import {
ScrollView,
Pressable as GesturizedPressable,
} from 'react-native-gesture-handler';

export default function Example() {
return (
<ScrollView>
<View style={styles.centering}>
<Text style={styles.text}>Gesturized Nested Pressables</Text>
<GesturizedBoxes />
<Text style={styles.text}>Legacy Nested Pressables</Text>
<LegacyBoxes />
</View>
</ScrollView>
);
}

const BOX_SIZE_COEFFICIENT = 100;

const getBoxStyle = (size: number): StyleProp<ViewStyle> => ({
width: size,
height: size,
borderWidth: 1,
});

const innerStyle = ({
pressed,
}: PressableStateCallbackType): StyleProp<ViewStyle> => [
getBoxStyle(BOX_SIZE_COEFFICIENT),
pressed ? { backgroundColor: '#c00' } : { backgroundColor: '#c77' },
styles.centering,
];
const middleStyle = ({
pressed,
}: PressableStateCallbackType): StyleProp<ViewStyle> => [
getBoxStyle(BOX_SIZE_COEFFICIENT * 2),
pressed ? { backgroundColor: '#0c0' } : { backgroundColor: '#7a7' },
styles.centering,
];
const outerStyle = ({
pressed,
}: PressableStateCallbackType): StyleProp<ViewStyle> => [
getBoxStyle(BOX_SIZE_COEFFICIENT * 3),
pressed ? { backgroundColor: '#00c' } : { backgroundColor: '#88a' },
styles.centering,
];

function GesturizedBoxes() {
return (
<GesturizedPressable style={outerStyle} testID="outer">
<GesturizedPressable style={middleStyle} testID="middle">
<GesturizedPressable style={innerStyle} testID="inner" />
</GesturizedPressable>
</GesturizedPressable>
);
}

function LegacyBoxes() {
return (
<LegacyPressable style={outerStyle}>
<LegacyPressable style={middleStyle}>
<LegacyPressable style={innerStyle} />
</LegacyPressable>
</LegacyPressable>
);
}

const styles = StyleSheet.create({
text: {
fontSize: 20,
margin: 20,
},
centering: {
alignItems: 'center',
justifyContent: 'center',
borderRadius: 6,
},
});
Loading

0 comments on commit e2098dc

Please sign in to comment.