-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Testing enhanced gesture approach #21369
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,14 +43,22 @@ export const TouchableOpacity = ({ | |
// Handle both 'disabled' and 'isDisabled' props for compatibility | ||
const isDisabled = disabled || (props as { isDisabled?: boolean }).isDisabled; | ||
|
||
// Track accessibility state - start with null to indicate "unknown" | ||
// Track accessibility state - start with false as default to ensure gesture handler works | ||
const [isAccessibilityEnabled, setIsAccessibilityEnabled] = useState< | ||
boolean | null | ||
>(null); | ||
>(false); | ||
|
||
useEffect(() => { | ||
// Check initial accessibility state | ||
AccessibilityInfo.isScreenReaderEnabled().then(setIsAccessibilityEnabled); | ||
AccessibilityInfo.isScreenReaderEnabled() | ||
.then(setIsAccessibilityEnabled) | ||
.catch((error) => { | ||
// Log the error for debugging | ||
console.warn('AccessibilityInfo.isScreenReaderEnabled failed:', error); | ||
// Fallback to false - assume accessibility is OFF | ||
// This ensures gesture handler will work in ScrollViews | ||
setIsAccessibilityEnabled(false); | ||
}); | ||
|
||
// Listen for accessibility changes | ||
const subscription = AccessibilityInfo.addEventListener( | ||
|
@@ -61,14 +69,16 @@ export const TouchableOpacity = ({ | |
return () => subscription?.remove(); | ||
}, []); | ||
|
||
// Gesture detection for ScrollView compatibility on Android | ||
// Native gesture handler to prevent interruption from other gestures (BottomSheet pan, etc.) | ||
const native = Gesture.Native().disallowInterruption(true); | ||
|
||
// Gesture detection for ScrollView and BottomSheet compatibility on Android | ||
const tap = Gesture.Tap() | ||
.runOnJS(true) | ||
.shouldCancelWhenOutside(false) | ||
.maxDeltaX(20) // Allow some movement while tapping | ||
.maxDeltaY(20) | ||
.requireExternalGestureToFail() // Wait for other gestures to fail before activating | ||
.maxDuration(300) // Tight constraint: must complete within 300ms | ||
.maxDuration(200) // Shorter duration for better responsiveness | ||
.minPointers(1) | ||
.onEnd( | ||
( | ||
|
@@ -116,12 +126,12 @@ export const TouchableOpacity = ({ | |
} | ||
|
||
return ( | ||
<GestureDetector gesture={tap}> | ||
<GestureDetector gesture={Gesture.Simultaneous(native, tap)}> | ||
<RNTouchableOpacity | ||
disabled={isDisabled} | ||
onPress={ | ||
isAccessibilityEnabled !== false && !isDisabled ? onPress : undefined | ||
} // Use TouchableOpacity onPress when accessibility is ON or UNKNOWN (safer for accessibility users) | ||
isAccessibilityEnabled === true && !isDisabled ? onPress : undefined | ||
} // Use TouchableOpacity onPress only when accessibility is explicitly ON (safer for accessibility users) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Accessibility Race Condition Disables Touch EventsThe updated accessibility logic introduces a critical issue where Additional Locations (2) |
||
{...props} | ||
> | ||
{children} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,14 +37,22 @@ const TouchableOpacity = ({ | |
}) => { | ||
const isDisabled = disabled || (props as { isDisabled?: boolean }).isDisabled; | ||
|
||
// Track accessibility state - start with null to indicate "unknown" | ||
// Track accessibility state - start with false as default to ensure gesture handler works | ||
const [isAccessibilityEnabled, setIsAccessibilityEnabled] = useState< | ||
boolean | null | ||
>(null); | ||
>(false); | ||
|
||
useEffect(() => { | ||
// Check initial accessibility state | ||
AccessibilityInfo.isScreenReaderEnabled().then(setIsAccessibilityEnabled); | ||
AccessibilityInfo.isScreenReaderEnabled() | ||
.then(setIsAccessibilityEnabled) | ||
.catch((error) => { | ||
// Log the error for debugging | ||
console.warn('AccessibilityInfo.isScreenReaderEnabled failed:', error); | ||
// Fallback to false - assume accessibility is OFF | ||
// This ensures gesture handler will work in ScrollViews | ||
setIsAccessibilityEnabled(false); | ||
}); | ||
|
||
// Listen for accessibility changes | ||
const subscription = AccessibilityInfo.addEventListener( | ||
|
@@ -55,14 +63,16 @@ const TouchableOpacity = ({ | |
return () => subscription?.remove(); | ||
}, []); | ||
|
||
// Gesture detection for ScrollView compatibility on Android | ||
// Native gesture handler to prevent interruption from other gestures (BottomSheet pan, etc.) | ||
const native = Gesture.Native().disallowInterruption(true); | ||
|
||
// Gesture detection for ScrollView and BottomSheet compatibility on Android | ||
const tap = Gesture.Tap() | ||
.runOnJS(true) | ||
.shouldCancelWhenOutside(false) | ||
.maxDeltaX(20) // Allow some movement while tapping | ||
.maxDeltaY(20) | ||
.requireExternalGestureToFail() // Wait for other gestures to fail before activating | ||
.maxDuration(300) // Tight constraint: must complete within 300ms | ||
.maxDuration(200) // Shorter duration for better responsiveness | ||
.minPointers(1) | ||
.onEnd( | ||
( | ||
|
@@ -110,12 +120,12 @@ const TouchableOpacity = ({ | |
} | ||
|
||
return ( | ||
<GestureDetector gesture={tap}> | ||
<GestureDetector gesture={Gesture.Simultaneous(native, tap)}> | ||
<RNTouchableOpacity | ||
disabled={isDisabled} | ||
onPress={ | ||
isAccessibilityEnabled !== false && !isDisabled ? onPress : undefined | ||
} // Use TouchableOpacity onPress when accessibility is ON or UNKNOWN (safer for accessibility users) | ||
isAccessibilityEnabled === true && !isDisabled ? onPress : undefined | ||
} // Use TouchableOpacity onPress only when accessibility is explicitly ON (safer for accessibility users) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Accessibility State Causes Component UnresponsivenessInitializing Additional Locations (2) |
||
{...props} | ||
> | ||
{children} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,11 +39,19 @@ const TouchableOpacity = ({ | |
// Track accessibility state - start with null to indicate "unknown" | ||
const [isAccessibilityEnabled, setIsAccessibilityEnabled] = useState< | ||
boolean | null | ||
>(null); | ||
>(false); | ||
|
||
useEffect(() => { | ||
// Check initial accessibility state | ||
AccessibilityInfo.isScreenReaderEnabled().then(setIsAccessibilityEnabled); | ||
AccessibilityInfo.isScreenReaderEnabled() | ||
.then(setIsAccessibilityEnabled) | ||
.catch((error) => { | ||
// Log the error for debugging | ||
console.warn('AccessibilityInfo.isScreenReaderEnabled failed:', error); | ||
// Fallback to false - assume accessibility is OFF | ||
// This ensures gesture handler will work in ScrollViews | ||
setIsAccessibilityEnabled(false); | ||
}); | ||
|
||
// Listen for accessibility changes | ||
const subscription = AccessibilityInfo.addEventListener( | ||
|
@@ -54,14 +62,16 @@ const TouchableOpacity = ({ | |
return () => subscription?.remove(); | ||
}, []); | ||
|
||
// Gesture detection for ScrollView compatibility on Android | ||
// Native gesture handler to prevent interruption from other gestures (BottomSheet pan, etc.) | ||
const native = Gesture.Native().disallowInterruption(true); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Gesture Handler Recreated on TouchableOpacity RenderThe native gesture handler is recreated on every render of the Additional Locations (2) |
||
|
||
// Gesture detection for ScrollView and BottomSheet compatibility on Android | ||
const tap = Gesture.Tap() | ||
.runOnJS(true) | ||
.shouldCancelWhenOutside(false) | ||
.maxDeltaX(20) // Allow some movement while tapping | ||
.maxDeltaY(20) | ||
.requireExternalGestureToFail() // Wait for other gestures to fail before activating | ||
.maxDuration(300) // Tight constraint: must complete within 300ms | ||
.maxDuration(200) // Shorter duration for better responsiveness | ||
.minPointers(1) | ||
.onEnd( | ||
( | ||
|
@@ -109,12 +119,12 @@ const TouchableOpacity = ({ | |
} | ||
|
||
return ( | ||
<GestureDetector gesture={tap}> | ||
<GestureDetector gesture={Gesture.Simultaneous(native, tap)}> | ||
<RNTouchableOpacity | ||
disabled={isDisabled} | ||
onPress={ | ||
isAccessibilityEnabled !== false && !isDisabled ? onPress : undefined | ||
} // Use TouchableOpacity onPress when accessibility is ON or UNKNOWN (safer for accessibility users) | ||
isAccessibilityEnabled === true && !isDisabled ? onPress : undefined | ||
} // Use TouchableOpacity onPress only when accessibility is explicitly ON (safer for accessibility users) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Accessibility Regression in Initial RenderThe change to initialize Additional Locations (2) |
||
{...props} | ||
> | ||
{children} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Gesture Configuration Blocks Tap Gestures
The updated gesture configuration, combining
Gesture.Simultaneous(native, tap)
withnative.disallowInterruption(true)
and removing.requireExternalGestureToFail()
, creates a conflict. This prevents tap gestures from executing, leading to unresponsive buttons and list items.Additional Locations (2)
app/component-library/components/List/ListItemMultiSelect/ListItemMultiSelect.tsx#L65-L123
app/component-library/components/List/ListItemSelect/ListItemSelect.tsx#L64-L122