/* eslint-disable react-native/no-inline-styles */ import { useSpacing } from '@mobily/stacks'; import React, { PropsWithChildren, RefObject, useCallback, useEffect, useRef } from 'react'; import BoxNucleon from '../../nucleons/BoxNucleon'; import AnimatedContextProvider, { useAnimatedContext } from './AnimatedContextProvider'; import Animated from 'react-native-reanimated'; import ArticleHeader from './ArticleHeader'; import { ImageRequireSource, View } from 'react-native'; import { useFocusEffect, useNavigation, useRoute } from '@react-navigation/core'; import ScrollerProvider, { useScroller } from './ScrollerProvider'; import { useSafeAreaInsets, useSafeAreaFrame } from 'react-native-safe-area-context'; import { PageSpecs } from '@doc/pages'; import UITideAtom, { UITideAtomProps } from '../../UITideAtom'; export interface ArticleTemplateProps { imageSource: ImageRequireSource; title: string; groupLabel: string; description: string; prevPage: PageSpecs | null; nextPage: PageSpecs | null; } interface ArticleProps extends ArticleTemplateProps { fragment?: string; scrollRef: RefObject; width: number; headerHeight: number; } const SCROLL_TO_DELAY = 500; function SiblingPageTide({ target, direction, ...props }: Omit & { target: PageSpecs; direction: 'prev' | 'next'; }) { const navigation = useNavigation(); return ( navigation.navigate(`${target.group}-${target.id}`), [navigation, target] )} /> ); } function Article({ children, fragment, scrollRef, width, headerHeight, prevPage, nextPage, ...props }: PropsWithChildren) { const { onScroll } = useAnimatedContext(); const { top: offsetTop, bottom: offsetBottom } = useSafeAreaInsets(); const scroller = useScroller(); useEffect( function updateOffset() { scroller.setOffset(headerHeight - offsetTop); }, [headerHeight, offsetTop, scroller] ); const scrollToFragment = useCallback( function scrollToFragment() { let timeout: any = null; function scrollTo() { if (fragment) { if (scroller.isLoaded) { scroller.scrollTo(fragment); } else { // reschedule timeout = setTimeout(scrollTo, SCROLL_TO_DELAY); } } else { scroller.scrollToTop(); } } timeout = setTimeout(scrollTo, SCROLL_TO_DELAY); return () => { timeout !== null && clearTimeout(timeout); }; }, [fragment, scroller] ); useFocusEffect(scrollToFragment); const gap = useSpacing(1); return ( <> scroller.setIsLoaded()} scrollEventThrottle={16} contentContainerStyle={[ { paddingTop: headerHeight, paddingBottom: offsetBottom } ]}> {children} {prevPage ? ( ) : ( )} {nextPage ? ( ) : ( )} ); } export default function ArticleTemplate( props: PropsWithChildren ) { const { params } = useRoute(); const { height: safeFrameHeight, width: safeFrameWidth } = useSafeAreaFrame(); const scrollRef = useRef() as RefObject; const fragment = (params as any)?.fragment; return (
); }