import _ from 'lodash'; import React, { useState, useCallback, useRef, useMemo, MutableRefObject, useEffect, useImperativeHandle } from 'react'; import { LayoutRectangle, StyleSheet, View, LayoutChangeEvent, Insets, TouchableOpacity, TouchableOpacityProps, GestureResponderEvent, I18nManager, Animated, Text } from 'react-native'; import MathjaxFactory from '../../mathjax/MathjaxFactory'; import MathView from '../../android/MathView'; import HitRectUtil, { defaultHitSlop, MathFragmentRect } from './HitRectUtil'; import * as TreeWalker from '../../mathjax/TreeWalker'; import { MathViewProps } from '../../common'; import { MathFragmentResponse } from '../../mathjax/MathjaxAdaptor'; function useLayout(initial = { x: 0, y: 0, width: 0, height: 0 }) { const [layout, setLayout] = useState(initial); const onLayout = useCallback((e: LayoutChangeEvent) => setLayout(e.nativeEvent.layout), []); return [layout, onLayout] as [LayoutRectangle, (e: LayoutChangeEvent) => void]; /* const layout = useRef({ x: 0, y: 0, width: 0, height: 0 }); const onLayout = useCallback((e: LayoutChangeEvent) => { _.set(layout, 'current', e.nativeEvent.layout) }, []); return [layout, onLayout] as [MutableRefObject, (e: LayoutChangeEvent) => void]; */ } interface FragmentedMathViewProps extends MathViewProps { hitSlop: number | Insets, dev: boolean } function FragmentedMathView(props: FragmentedMathViewProps, ref: any) { const [layout, onLayout] = useLayout(null); //const data = useMemo(() => layout && MathjaxFactory().toSVGArray(props.math), [layout, props.math]); const [data, setData] = useState(); const hitRectUtil = useMemo(() => new HitRectUtil(), []); useEffect(() => { if (!layout) return; setData(MathjaxFactory().toSVGArray(props.math)); }, [props.math, layout]); useEffect(() => { if (layout && data) hitRectUtil.set(layout, data); }, [layout, data, hitRectUtil]); useEffect(() => { hitRectUtil.setHitSlop(props.hitSlop); }, [props.hitSlop, hitRectUtil]); const __ref = useRef(); const anima = useMemo(() => _.map(new Array(_.size(data)), () => new Animated.Value(1)), [data]); const animaF = useMemo(() => _.map(data, ({ viewBox }, i) => { if (!layout || !data) return; const rect = new MathFragmentRect().setRect(layout, viewBox); return Animated.multiply(layout.width * 0.5 - rect.left, Animated.subtract(anima[i], 1)); }), [layout, data, anima]); //console.warn('FragmentedMathView bug intializng ref, unmount and remount and see if you manage to cet the ref') useImperativeHandle(ref, () => _.assign({}, __ref.current, { test: (x: number, y: number) => hitRectUtil.test(x, y), __test: (x: number, y: number) => { // console.log(test.current(x, y)) const hitResult = hitRectUtil.test(x, y); /* const augment = _.map(hitResult, (arg) => { return arg.namespace.char.match(/[a-zA-Z]/) ? _.filter(data, ({ node: n }) => _.isEqual(arg.node.parent, n.parent)) : [arg.node]; }); */ _.map(hitResult, ({ node, namespace, index, hitResult }) => { anima[index].setValue(2); Animated.spring(anima[index], { toValue: 1, useNativeDriver: true, delay: 100 }).start(); /* TreeWalker.walkUp(node, (n, l) => { namespace.char.match(/[a-zA-Z]/) }) */ console.log(namespace.char) }); }, __pip() { _.map(new Array(data.length), (a, i) => anima[i].setValue(2)) setTimeout(() => { }, 200) Animated.stagger( 50, _.concat( // _.map(new Array(data.length), (a, i) => Animated.spring(anima[i], { toValue: 2, useNativeDriver: true })), _.map(new Array(data.length), (a, i) => Animated.spring(anima[i], { toValue: 1, useNativeDriver: true, delay: 500 })), ) ).start(); } })); return ( {layout && data && _.map(data, ({ svg, viewBox, namespace: { char } }, index) => { return ( ); })} {__DEV__ && props.dev && layout && _.map(data, ({ svg, viewBox, namespace: { char } }, index) => { const rect = _.pick(new MathFragmentRect().setRect(layout, viewBox), 'left', 'top', 'right', 'bottom', 'width', 'height'); return ( {char} ); })} ); /* return ( {_.map(_.reject(MathjaxFactory().splitMath(props.math), math => math.match(/((\\left)|(\\right))|(\\frac)/)), (math, index) => { const svg = MathjaxFactory().toSVG(math); console.log(math, svg) return ( console.log(index)} /> ) })} ); */ } const styles = StyleSheet.create({ flexContainer: { display: 'flex', flexDirection: I18nManager.isRTL ? 'row-reverse' : 'row', //justifyContent: 'flex-end' }, }); const FragmentedMathViewWrapper = React.forwardRef(FragmentedMathView); FragmentedMathViewWrapper.defaultProps = FragmentedMathView.defaultProps = { resizeMode: 'contain', hitSlop: defaultHitSlop, dev: false } as Partial; export default FragmentedMathViewWrapper;