mirror of
https://github.com/tooot-app/app
synced 2025-03-12 09:30:11 +01:00
Added fetched notice
This commit is contained in:
parent
aee206fc95
commit
d1714fab26
@ -17,6 +17,7 @@ import Animated, {
|
|||||||
Extrapolate,
|
Extrapolate,
|
||||||
interpolate,
|
interpolate,
|
||||||
runOnJS,
|
runOnJS,
|
||||||
|
SharedValue,
|
||||||
useAnimatedReaction,
|
useAnimatedReaction,
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
useDerivedValue,
|
useDerivedValue,
|
||||||
@ -28,6 +29,7 @@ export interface Props {
|
|||||||
flRef: RefObject<FlatList<any>>
|
flRef: RefObject<FlatList<any>>
|
||||||
queryKey: QueryKeyTimeline
|
queryKey: QueryKeyTimeline
|
||||||
fetchingActive: React.MutableRefObject<boolean>
|
fetchingActive: React.MutableRefObject<boolean>
|
||||||
|
setFetchedCount: React.Dispatch<React.SetStateAction<number | null>>
|
||||||
scrollY: Animated.SharedValue<number>
|
scrollY: Animated.SharedValue<number>
|
||||||
fetchingType: Animated.SharedValue<0 | 1 | 2>
|
fetchingType: Animated.SharedValue<0 | 1 | 2>
|
||||||
disableRefresh?: boolean
|
disableRefresh?: boolean
|
||||||
@ -42,6 +44,7 @@ const TimelineRefresh: React.FC<Props> = ({
|
|||||||
flRef,
|
flRef,
|
||||||
queryKey,
|
queryKey,
|
||||||
fetchingActive,
|
fetchingActive,
|
||||||
|
setFetchedCount,
|
||||||
scrollY,
|
scrollY,
|
||||||
fetchingType,
|
fetchingType,
|
||||||
disableRefresh = false,
|
disableRefresh = false,
|
||||||
@ -152,6 +155,8 @@ const TimelineRefresh: React.FC<Props> = ({
|
|||||||
meta: {}
|
meta: {}
|
||||||
})
|
})
|
||||||
.then(res => {
|
.then(res => {
|
||||||
|
setFetchedCount(res.body.length)
|
||||||
|
|
||||||
if (!res.body.length) return
|
if (!res.body.length) return
|
||||||
|
|
||||||
queryClient.setQueryData<
|
queryClient.setQueryData<
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import ComponentSeparator from '@components/Separator'
|
import ComponentSeparator from '@components/Separator'
|
||||||
|
import CustomText from '@components/Text'
|
||||||
import TimelineDefault from '@components/Timeline/Default'
|
import TimelineDefault from '@components/Timeline/Default'
|
||||||
import { useScrollToTop } from '@react-navigation/native'
|
import { useScrollToTop } from '@react-navigation/native'
|
||||||
import { UseInfiniteQueryOptions } from '@tanstack/react-query'
|
import { UseInfiniteQueryOptions } from '@tanstack/react-query'
|
||||||
@ -11,9 +12,20 @@ import {
|
|||||||
} from '@utils/storage/actions'
|
} from '@utils/storage/actions'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import React, { RefObject, useRef } from 'react'
|
import React, { RefObject, useRef, useState } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
import { FlatList, FlatListProps, Platform, RefreshControl } from 'react-native'
|
import { FlatList, FlatListProps, Platform, RefreshControl } from 'react-native'
|
||||||
import Animated, { useAnimatedScrollHandler, useSharedValue } from 'react-native-reanimated'
|
import Animated, {
|
||||||
|
Easing,
|
||||||
|
runOnJS,
|
||||||
|
useAnimatedScrollHandler,
|
||||||
|
useAnimatedStyle,
|
||||||
|
useDerivedValue,
|
||||||
|
useSharedValue,
|
||||||
|
withDelay,
|
||||||
|
withSequence,
|
||||||
|
withTiming
|
||||||
|
} from 'react-native-reanimated'
|
||||||
import TimelineEmpty from './Empty'
|
import TimelineEmpty from './Empty'
|
||||||
import TimelineFooter from './Footer'
|
import TimelineFooter from './Footer'
|
||||||
import TimelineRefresh, { SEPARATION_Y_1, SEPARATION_Y_2 } from './Refresh'
|
import TimelineRefresh, { SEPARATION_Y_1, SEPARATION_Y_2 } from './Refresh'
|
||||||
@ -42,9 +54,10 @@ const Timeline: React.FC<Props> = ({
|
|||||||
readMarker = undefined,
|
readMarker = undefined,
|
||||||
customProps
|
customProps
|
||||||
}) => {
|
}) => {
|
||||||
const { colors } = useTheme()
|
const { colors, theme } = useTheme()
|
||||||
|
const { t } = useTranslation('componentTimeline')
|
||||||
|
|
||||||
const { data, refetch, isFetching, isLoading, fetchNextPage, isFetchingNextPage } =
|
const { data, refetch, isFetching, isLoading, isRefetching, fetchNextPage, isFetchingNextPage } =
|
||||||
useTimelineQuery({
|
useTimelineQuery({
|
||||||
...queryKey[1],
|
...queryKey[1],
|
||||||
options: {
|
options: {
|
||||||
@ -58,6 +71,28 @@ const Timeline: React.FC<Props> = ({
|
|||||||
|
|
||||||
const flRef = useRef<FlatList>(null)
|
const flRef = useRef<FlatList>(null)
|
||||||
const fetchingActive = useRef<boolean>(false)
|
const fetchingActive = useRef<boolean>(false)
|
||||||
|
const [fetchedCount, setFetchedCount] = useState<number | null>(null)
|
||||||
|
const fetchedNoticeHeight = useSharedValue<number>(100)
|
||||||
|
const fetchedNoticeTop = useDerivedValue(() => {
|
||||||
|
if ((!isLoading && !isRefetching && isFetching) || fetchedCount !== null) {
|
||||||
|
return withSequence(
|
||||||
|
withTiming(fetchedNoticeHeight.value + 16 + 4),
|
||||||
|
withDelay(
|
||||||
|
2000,
|
||||||
|
withTiming(0, { easing: Easing.out(Easing.ease) }, finished => {
|
||||||
|
if (finished) {
|
||||||
|
runOnJS(setFetchedCount)(null)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}, [isLoading, isRefetching, isFetching, fetchedCount])
|
||||||
|
const fetchedNoticeAnimate = useAnimatedStyle(() => ({
|
||||||
|
transform: [{ translateY: fetchedNoticeTop.value }]
|
||||||
|
}))
|
||||||
|
|
||||||
const scrollY = useSharedValue(0)
|
const scrollY = useSharedValue(0)
|
||||||
const fetchingType = useSharedValue<0 | 1 | 2>(0)
|
const fetchingType = useSharedValue<0 | 1 | 2>(0)
|
||||||
@ -96,9 +131,9 @@ const Timeline: React.FC<Props> = ({
|
|||||||
|
|
||||||
const firstItemId = viewableItems.filter(item => item.isViewable)[0]?.item.id
|
const firstItemId = viewableItems.filter(item => item.isViewable)[0]?.item.id
|
||||||
if (!fetchingActive.current && firstItemId && firstItemId > (marker || '0')) {
|
if (!fetchingActive.current && firstItemId && firstItemId > (marker || '0')) {
|
||||||
setAccountStorage([{ key: readMarker, value: firstItemId }])
|
// setAccountStorage([{ key: readMarker, value: firstItemId }])
|
||||||
} else {
|
} else {
|
||||||
// setAccountStorage([{ key: readMarker, value: '109519141378761752' }])
|
setAccountStorage([{ key: readMarker, value: '109519141378761752' }])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,6 +171,7 @@ const Timeline: React.FC<Props> = ({
|
|||||||
flRef={flRef}
|
flRef={flRef}
|
||||||
queryKey={queryKey}
|
queryKey={queryKey}
|
||||||
fetchingActive={fetchingActive}
|
fetchingActive={fetchingActive}
|
||||||
|
setFetchedCount={setFetchedCount}
|
||||||
scrollY={scrollY}
|
scrollY={scrollY}
|
||||||
fetchingType={fetchingType}
|
fetchingType={fetchingType}
|
||||||
disableRefresh={disableRefresh}
|
disableRefresh={disableRefresh}
|
||||||
@ -176,6 +212,44 @@ const Timeline: React.FC<Props> = ({
|
|||||||
{...androidRefreshControl}
|
{...androidRefreshControl}
|
||||||
{...customProps}
|
{...customProps}
|
||||||
/>
|
/>
|
||||||
|
{!disableRefresh ? (
|
||||||
|
<Animated.View
|
||||||
|
style={[
|
||||||
|
{
|
||||||
|
position: 'absolute',
|
||||||
|
alignSelf: 'center',
|
||||||
|
top: -fetchedNoticeHeight.value - 16,
|
||||||
|
paddingVertical: StyleConstants.Spacing.S,
|
||||||
|
paddingHorizontal: StyleConstants.Spacing.M,
|
||||||
|
backgroundColor: colors.backgroundDefault,
|
||||||
|
shadowColor: colors.primaryDefault,
|
||||||
|
shadowOffset: { width: 0, height: 0 },
|
||||||
|
shadowOpacity: theme === 'light' ? 0.16 : 0.24,
|
||||||
|
borderRadius: 99,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
fetchedNoticeAnimate
|
||||||
|
]}
|
||||||
|
onLayout={({
|
||||||
|
nativeEvent: {
|
||||||
|
layout: { height }
|
||||||
|
}
|
||||||
|
}) => (fetchedNoticeHeight.value = height)}
|
||||||
|
>
|
||||||
|
<CustomText
|
||||||
|
fontStyle='M'
|
||||||
|
style={{ color: colors.primaryDefault }}
|
||||||
|
children={
|
||||||
|
fetchedCount !== null
|
||||||
|
? fetchedCount > 0
|
||||||
|
? t('refresh.fetched.found', { count: fetchedCount })
|
||||||
|
: t('refresh.fetched.none')
|
||||||
|
: t('refresh.fetching')
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Animated.View>
|
||||||
|
) : null}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,12 @@
|
|||||||
},
|
},
|
||||||
"refresh": {
|
"refresh": {
|
||||||
"fetchPreviousPage": "Newer from here",
|
"fetchPreviousPage": "Newer from here",
|
||||||
"refetch": "To latest"
|
"refetch": "To latest",
|
||||||
|
"fetching": "Fetching newer toots ...",
|
||||||
|
"fetched": {
|
||||||
|
"none": "No newer toot",
|
||||||
|
"found": "Fetched {{count}} toots"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"shared": {
|
"shared": {
|
||||||
"actioned": {
|
"actioned": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user