Skip to content

Instantly share code, notes, and snippets.

@NilsonLima
Last active May 7, 2021 14:54
Show Gist options
  • Save NilsonLima/8c7e3d148143b34ac80c759ee64d4cb2 to your computer and use it in GitHub Desktop.
Save NilsonLima/8c7e3d148143b34ac80c759ee64d4cb2 to your computer and use it in GitHub Desktop.
TouchTester
/* Circle.js */
import { View } from 'react-native';
function Circle({ style, radius, color }) {
return (
<View
style={[
{
width: radius * 2,
height: radius * 2,
borderRadius: radius,
backgroundColor: color,
},
style,
]}
/>
);
}
export default Circle;
/* Countdown.js */
import { useImperativeHandle, forwardRef } from 'react';
import { View, Text } from 'react-native';
import useCountdown from './hooks/useCountdown'; // custom hook to handle countdown
function Countdown({ time, containerStyle, onFinish, ref }) {
const { second, start } = useCountdown(time, onFinish);
useImperativeHandle(ref, () => ({
start
}));
return (
<View style={containerStyle}>
<Text>{second}</Text>
</View>
);
}
export default forwardRef(Countdown);
/* Matrix.js */
import { useMemo } from 'react';
import { View, Animated } from 'react-native';
import { PanGestureHandler } from 'react-native-gesture-handler';
import useDimensions from 'hooks/useDimensions'; // hypothetical custom hook to get screen dimensions
import Circle from './Circle';
function Matrix({ itemSize, subjectStyle, onSubjectMove }) {
const { dimensions } = useDimensions();
// Build collection to render matrix using Array.map function
const matrix = useMemo(() => buildMatrix(itemSize, dimensions), [itemSize, dimensions]);
const killCircle = useCallback(index => ..., [matrix]); // hypothetical function to clear overlapped circle
const handleGesture = event => {
/* matchCircle returns true when matrix is empty */
onSubjectMove({ ...event, isEmpty: matchCircles(event, matrix, killCircle) });
};
return (
<View style={ /*pass style to flex-wrap children*/ }>
{
matrix.map(circle => {
const atCenter = isCentered(circle);
const Container = atCenter ? PanGestureHandler : View;
// can be replaced by another shape like `Square`
const Subject = atCenter ? Animated.createAnimatedComponent(Circle) : Circle;
return (
<Container onGestureEvent={handleGesture}>
<Subject
radius={itemSize}
style={subjectStyle}
color={atCenter ? 'secondary' : 'primary'}
/>
</Container>
);
});
}
</View>
);
}
export default Matrix;
/* TouchTester.js */
import { useCallback, useRef } from 'react';
import { SafeAreaView, Button } from 'react-native';
import Countdown from './Countdown';
import Matrix from './Matrix';
import useTranslated from './hooks/useTranslated'; // custom hook which makes the magic
function TouchTester() {
const { translated, handler } = useTranslated();
const countdown = useRef(null);
const onSubjectMove = useCallback(event => {
if (event.isEmpty) return; // finish succeeded test
handler(event);
}, [handler]);
return (
<SafeAreaView style={{ flex: 1 }}>
<Matrix
itemSize={25}
subjectStyle={{
transform: [{ translateY : translated.y }, { translateX : translated.x }]
}}
onSubjectMove={onSubjectMove}
/>
<Countdown ref={countdown} time={30} onFinish={/* pass function to fail test */} />
<Button onPress={countdown?.current.start}>{'Iniciar teste'}</Button>
</SafeAreaView>
);
}
export default TouchTester;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment