diff --git a/src/components/Timeline/Refresh.tsx b/src/components/Timeline/Refresh.tsx index 221cd6bb..1a183df4 100644 --- a/src/components/Timeline/Refresh.tsx +++ b/src/components/Timeline/Refresh.tsx @@ -20,7 +20,6 @@ import Animated, { SharedValue, useAnimatedReaction, useAnimatedStyle, - useDerivedValue, useSharedValue, withTiming } from 'react-native-reanimated' @@ -28,10 +27,10 @@ import Animated, { export interface Props { flRef: RefObject> queryKey: QueryKeyTimeline - fetchingActive: React.MutableRefObject + isFetchingPrev: SharedValue setFetchedCount: React.Dispatch> - scrollY: Animated.SharedValue - fetchingType: Animated.SharedValue<0 | 1 | 2> + scrollY: SharedValue + fetchingType: SharedValue<0 | 1 | 2> disableRefresh?: boolean readMarker?: 'read_marker_following' } @@ -43,7 +42,7 @@ export const SEPARATION_Y_2 = -(CONTAINER_HEIGHT * 1.5 + StyleConstants.Font.Siz const TimelineRefresh: React.FC = ({ flRef, queryKey, - fetchingActive, + isFetchingPrev, setFetchedCount, scrollY, fetchingType, @@ -58,20 +57,11 @@ const TimelineRefresh: React.FC = ({ } const PREV_PER_BATCH = 1 - const prevActive = useRef(false) const prevCache = useRef<(Mastodon.Status | Mastodon.Notification | Mastodon.Conversation)[]>() const prevStatusId = useRef() const queryClient = useQueryClient() - const { refetch, isRefetching } = useTimelineQuery({ ...queryKey[1] }) - - useDerivedValue(() => { - if (prevActive.current || isRefetching) { - fetchingActive.current = true - } else { - fetchingActive.current = false - } - }, [prevActive.current, isRefetching]) + const { refetch } = useTimelineQuery({ ...queryKey[1] }) const { t } = useTranslation('componentTimeline') const { colors } = useTheme() @@ -99,7 +89,7 @@ const TimelineRefresh: React.FC = ({ const arrowStage = useSharedValue(0) useAnimatedReaction( () => { - if (fetchingActive.current) { + if (isFetchingPrev.value) { return false } switch (arrowStage.value) { @@ -131,13 +121,12 @@ const TimelineRefresh: React.FC = ({ if (data) { runOnJS(haptics)('Light') } - }, - [fetchingActive.current] + } ) const fetchAndScrolled = useSharedValue(false) const runFetchPrevious = async () => { - if (prevActive.current) return + if (isFetchingPrev.value) return const firstPage = queryClient.getQueryData< @@ -146,7 +135,7 @@ const TimelineRefresh: React.FC = ({ > >(queryKey)?.pages[0] - prevActive.current = true + isFetchingPrev.value = true prevStatusId.current = firstPage?.body[0]?.id await queryFunctionTimeline({ @@ -154,7 +143,7 @@ const TimelineRefresh: React.FC = ({ pageParam: firstPage?.links?.prev, meta: {} }) - .then(res => { + .then(async res => { setFetchedCount(res.body.length) if (!res.body.length) return @@ -177,7 +166,7 @@ const TimelineRefresh: React.FC = ({ }) .then(async nextLength => { if (!nextLength) { - prevActive.current = false + isFetchingPrev.value = false return } @@ -214,7 +203,7 @@ const TimelineRefresh: React.FC = ({ } }) } - prevActive.current = false + isFetchingPrev.value = false }) } diff --git a/src/components/Timeline/index.tsx b/src/components/Timeline/index.tsx index 7478727b..c307a131 100644 --- a/src/components/Timeline/index.tsx +++ b/src/components/Timeline/index.tsx @@ -18,6 +18,7 @@ import { FlatList, FlatListProps, Platform, RefreshControl } from 'react-native' import Animated, { Easing, runOnJS, + useAnimatedReaction, useAnimatedScrollHandler, useAnimatedStyle, useDerivedValue, @@ -70,26 +71,44 @@ const Timeline: React.FC = ({ }) const flRef = useRef(null) - const fetchingActive = useRef(false) + const isFetchingPrev = useSharedValue(false) const [fetchedCount, setFetchedCount] = useState(null) const fetchedNoticeHeight = useSharedValue(100) + const notifiedFetchedNotice = useSharedValue(false) + useAnimatedReaction( + () => isFetchingPrev.value, + (curr, prev) => { + if (curr === true && prev === false) { + notifiedFetchedNotice.value = true + } + } + ) + useAnimatedReaction( + () => fetchedCount, + (curr, prev) => { + if (curr !== null && prev === null) { + notifiedFetchedNotice.value = false + } + }, + [fetchedCount] + ) const fetchedNoticeTop = useDerivedValue(() => { - if ((!isLoading && !isRefetching && isFetching) || fetchedCount !== null) { + if (notifiedFetchedNotice.value || fetchedCount !== null) { return withSequence( withTiming(fetchedNoticeHeight.value + 16 + 4), withDelay( 2000, - withTiming(0, { easing: Easing.out(Easing.ease) }, finished => { - if (finished) { - runOnJS(setFetchedCount)(null) - } - }) + withTiming( + 0, + { easing: Easing.out(Easing.ease) }, + finished => finished && runOnJS(setFetchedCount)(null) + ) ) ) } else { return 0 } - }, [isLoading, isRefetching, isFetching, fetchedCount]) + }, [fetchedCount]) const fetchedNoticeAnimate = useAnimatedStyle(() => ({ transform: [{ translateY: fetchedNoticeTop.value }] })) @@ -130,7 +149,12 @@ const Timeline: React.FC = ({ const marker = readMarker ? getAccountStorage.string(readMarker) : undefined const firstItemId = viewableItems.filter(item => item.isViewable)[0]?.item.id - if (!fetchingActive.current && firstItemId && firstItemId > (marker || '0')) { + if ( + !isFetchingPrev.value && + !isRefetching && + firstItemId && + firstItemId > (marker || '0') + ) { setAccountStorage([{ key: readMarker, value: firstItemId }]) } else { // setAccountStorage([{ key: readMarker, value: '109519141378761752' }]) @@ -170,7 +194,7 @@ const Timeline: React.FC = ({ = ({ }) => (fetchedNoticeHeight.value = height)} >