From 6f44866c485b6a0aae953dd30f260870d1092a05 Mon Sep 17 00:00:00 2001 From: Stacy Sun Date: Thu, 26 Feb 2026 15:35:29 -0800 Subject: [PATCH] test Numpad --- .../src/numpad/__stories__/Numpad.stories.tsx | 149 +++++++++++++++++- 1 file changed, 145 insertions(+), 4 deletions(-) diff --git a/packages/mobile/src/numpad/__stories__/Numpad.stories.tsx b/packages/mobile/src/numpad/__stories__/Numpad.stories.tsx index 112a95b5d..fbfa15948 100644 --- a/packages/mobile/src/numpad/__stories__/Numpad.stories.tsx +++ b/packages/mobile/src/numpad/__stories__/Numpad.stories.tsx @@ -1,5 +1,5 @@ -import { useCallback, useMemo, useState } from 'react'; -import { View } from 'react-native'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { Animated, ScrollView, View } from 'react-native'; import { Banner } from '../../banner/Banner'; import { Button, ButtonGroup } from '../../buttons'; @@ -9,6 +9,7 @@ import { useSafeBottomPadding } from '../../hooks/useSafeBottomPadding'; import { useTheme } from '../../hooks/useTheme'; import { Box, HStack, VStack } from '../../layout'; import { Modal, ModalBody, ModalHeader } from '../../overlays'; +import { Pressable } from '../../system/Pressable'; import { Text } from '../../typography/Text'; import type { NumpadValue } from '../Numpad'; import { DELETE, Numpad, SEPARATOR } from '../Numpad'; @@ -208,15 +209,155 @@ const NumpadExample2 = () => { ); }; +/** + * Stress test to reproduce Android Fabric crash with rapid button presses. + * This example adds load to the screen: + * - Background state updates (counter incrementing) + * - Multiple animated components + * - Additional Pressable buttons + * - ScrollView with content + */ +const NumpadStressTest = () => { + const theme = useTheme(); + const [value, setValue] = useState(''); + const [pressCount, setPressCount] = useState(0); + const [backgroundCounter, setBackgroundCounter] = useState(0); + + // Background state updates to add load + useEffect(() => { + const interval = setInterval(() => { + setBackgroundCounter((prev) => prev + 1); + }, 100); // Update every 100ms + return () => clearInterval(interval); + }, []); + + // Animated values for additional load + const pulseAnim = useMemo(() => new Animated.Value(1), []); + + useEffect(() => { + const pulse = Animated.loop( + Animated.sequence([ + Animated.timing(pulseAnim, { + toValue: 1.1, + duration: 500, + useNativeDriver: true, + }), + Animated.timing(pulseAnim, { + toValue: 1, + duration: 500, + useNativeDriver: true, + }), + ]), + ); + pulse.start(); + return () => pulse.stop(); + }, [pulseAnim]); + + const onPress = useCallback((input: NumpadValue) => { + setPressCount((prev) => prev + 1); + if (input === DELETE) { + setValue((prev) => prev.slice(0, -1)); + } else if (input !== SEPARATOR) { + setValue((prev) => prev + input); + } + }, []); + + const onLongPress = useCallback((input: NumpadValue) => { + if (input === DELETE) { + setValue(''); + } + }, []); + + return ( + + {/* Header with animated element and background counter */} + + + + Stress Test + + Press buttons rapidly to test + + + + + + {pressCount} + + + + + + Background updates: {backgroundCounter} + + + + {/* Additional Pressable buttons to add more Animated.View instances */} + + + {Array.from({ length: 20 }).map((_, i) => ( + setPressCount((prev) => prev + 1)} + padding={2} + > + Btn {i + 1} + + ))} + + + + {/* Value display */} + + {value || '0'} + + + {/* Numpad */} + + + + + {/* Footer with more animated elements */} + + + {Array.from({ length: 4 }).map((_, i) => ( + + + + ))} + + + + ); +}; + const NumpadScreen = () => { return ( - + + + Rapidly press numpad buttons to test for crashes on Android with New Architecture + + + + + + {/* - + */} ); };