1
0
mirror of https://github.com/tooot-app/app synced 2025-03-12 17:40:19 +01:00

Improve notify animation

This commit is contained in:
xmflsct 2023-01-30 13:40:43 +01:00
parent 7559196e42
commit 646b539949
2 changed files with 47 additions and 34 deletions

View File

@ -20,7 +20,6 @@ import Animated, {
SharedValue, SharedValue,
useAnimatedReaction, useAnimatedReaction,
useAnimatedStyle, useAnimatedStyle,
useDerivedValue,
useSharedValue, useSharedValue,
withTiming withTiming
} from 'react-native-reanimated' } from 'react-native-reanimated'
@ -28,10 +27,10 @@ import Animated, {
export interface Props { export interface Props {
flRef: RefObject<FlatList<any>> flRef: RefObject<FlatList<any>>
queryKey: QueryKeyTimeline queryKey: QueryKeyTimeline
fetchingActive: React.MutableRefObject<boolean> isFetchingPrev: SharedValue<boolean>
setFetchedCount: React.Dispatch<React.SetStateAction<number | null>> setFetchedCount: React.Dispatch<React.SetStateAction<number | null>>
scrollY: Animated.SharedValue<number> scrollY: SharedValue<number>
fetchingType: Animated.SharedValue<0 | 1 | 2> fetchingType: SharedValue<0 | 1 | 2>
disableRefresh?: boolean disableRefresh?: boolean
readMarker?: 'read_marker_following' readMarker?: 'read_marker_following'
} }
@ -43,7 +42,7 @@ export const SEPARATION_Y_2 = -(CONTAINER_HEIGHT * 1.5 + StyleConstants.Font.Siz
const TimelineRefresh: React.FC<Props> = ({ const TimelineRefresh: React.FC<Props> = ({
flRef, flRef,
queryKey, queryKey,
fetchingActive, isFetchingPrev,
setFetchedCount, setFetchedCount,
scrollY, scrollY,
fetchingType, fetchingType,
@ -58,20 +57,11 @@ const TimelineRefresh: React.FC<Props> = ({
} }
const PREV_PER_BATCH = 1 const PREV_PER_BATCH = 1
const prevActive = useRef<boolean>(false)
const prevCache = useRef<(Mastodon.Status | Mastodon.Notification | Mastodon.Conversation)[]>() const prevCache = useRef<(Mastodon.Status | Mastodon.Notification | Mastodon.Conversation)[]>()
const prevStatusId = useRef<Mastodon.Status['id']>() const prevStatusId = useRef<Mastodon.Status['id']>()
const queryClient = useQueryClient() const queryClient = useQueryClient()
const { refetch, isRefetching } = useTimelineQuery({ ...queryKey[1] }) const { refetch } = useTimelineQuery({ ...queryKey[1] })
useDerivedValue(() => {
if (prevActive.current || isRefetching) {
fetchingActive.current = true
} else {
fetchingActive.current = false
}
}, [prevActive.current, isRefetching])
const { t } = useTranslation('componentTimeline') const { t } = useTranslation('componentTimeline')
const { colors } = useTheme() const { colors } = useTheme()
@ -99,7 +89,7 @@ const TimelineRefresh: React.FC<Props> = ({
const arrowStage = useSharedValue(0) const arrowStage = useSharedValue(0)
useAnimatedReaction( useAnimatedReaction(
() => { () => {
if (fetchingActive.current) { if (isFetchingPrev.value) {
return false return false
} }
switch (arrowStage.value) { switch (arrowStage.value) {
@ -131,13 +121,12 @@ const TimelineRefresh: React.FC<Props> = ({
if (data) { if (data) {
runOnJS(haptics)('Light') runOnJS(haptics)('Light')
} }
}, }
[fetchingActive.current]
) )
const fetchAndScrolled = useSharedValue(false) const fetchAndScrolled = useSharedValue(false)
const runFetchPrevious = async () => { const runFetchPrevious = async () => {
if (prevActive.current) return if (isFetchingPrev.value) return
const firstPage = const firstPage =
queryClient.getQueryData< queryClient.getQueryData<
@ -146,7 +135,7 @@ const TimelineRefresh: React.FC<Props> = ({
> >
>(queryKey)?.pages[0] >(queryKey)?.pages[0]
prevActive.current = true isFetchingPrev.value = true
prevStatusId.current = firstPage?.body[0]?.id prevStatusId.current = firstPage?.body[0]?.id
await queryFunctionTimeline({ await queryFunctionTimeline({
@ -154,7 +143,7 @@ const TimelineRefresh: React.FC<Props> = ({
pageParam: firstPage?.links?.prev, pageParam: firstPage?.links?.prev,
meta: {} meta: {}
}) })
.then(res => { .then(async res => {
setFetchedCount(res.body.length) setFetchedCount(res.body.length)
if (!res.body.length) return if (!res.body.length) return
@ -177,7 +166,7 @@ const TimelineRefresh: React.FC<Props> = ({
}) })
.then(async nextLength => { .then(async nextLength => {
if (!nextLength) { if (!nextLength) {
prevActive.current = false isFetchingPrev.value = false
return return
} }
@ -214,7 +203,7 @@ const TimelineRefresh: React.FC<Props> = ({
} }
}) })
} }
prevActive.current = false isFetchingPrev.value = false
}) })
} }

View File

@ -18,6 +18,7 @@ import { FlatList, FlatListProps, Platform, RefreshControl } from 'react-native'
import Animated, { import Animated, {
Easing, Easing,
runOnJS, runOnJS,
useAnimatedReaction,
useAnimatedScrollHandler, useAnimatedScrollHandler,
useAnimatedStyle, useAnimatedStyle,
useDerivedValue, useDerivedValue,
@ -70,26 +71,44 @@ const Timeline: React.FC<Props> = ({
}) })
const flRef = useRef<FlatList>(null) const flRef = useRef<FlatList>(null)
const fetchingActive = useRef<boolean>(false) const isFetchingPrev = useSharedValue<boolean>(false)
const [fetchedCount, setFetchedCount] = useState<number | null>(null) const [fetchedCount, setFetchedCount] = useState<number | null>(null)
const fetchedNoticeHeight = useSharedValue<number>(100) const fetchedNoticeHeight = useSharedValue<number>(100)
const notifiedFetchedNotice = useSharedValue<boolean>(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(() => { const fetchedNoticeTop = useDerivedValue(() => {
if ((!isLoading && !isRefetching && isFetching) || fetchedCount !== null) { if (notifiedFetchedNotice.value || fetchedCount !== null) {
return withSequence( return withSequence(
withTiming(fetchedNoticeHeight.value + 16 + 4), withTiming(fetchedNoticeHeight.value + 16 + 4),
withDelay( withDelay(
2000, 2000,
withTiming(0, { easing: Easing.out(Easing.ease) }, finished => { withTiming(
if (finished) { 0,
runOnJS(setFetchedCount)(null) { easing: Easing.out(Easing.ease) },
} finished => finished && runOnJS(setFetchedCount)(null)
}) )
) )
) )
} else { } else {
return 0 return 0
} }
}, [isLoading, isRefetching, isFetching, fetchedCount]) }, [fetchedCount])
const fetchedNoticeAnimate = useAnimatedStyle(() => ({ const fetchedNoticeAnimate = useAnimatedStyle(() => ({
transform: [{ translateY: fetchedNoticeTop.value }] transform: [{ translateY: fetchedNoticeTop.value }]
})) }))
@ -130,7 +149,12 @@ const Timeline: React.FC<Props> = ({
const marker = readMarker ? getAccountStorage.string(readMarker) : undefined const marker = readMarker ? getAccountStorage.string(readMarker) : undefined
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 (
!isFetchingPrev.value &&
!isRefetching &&
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' }])
@ -170,7 +194,7 @@ const Timeline: React.FC<Props> = ({
<TimelineRefresh <TimelineRefresh
flRef={flRef} flRef={flRef}
queryKey={queryKey} queryKey={queryKey}
fetchingActive={fetchingActive} isFetchingPrev={isFetchingPrev}
setFetchedCount={setFetchedCount} setFetchedCount={setFetchedCount}
scrollY={scrollY} scrollY={scrollY}
fetchingType={fetchingType} fetchingType={fetchingType}
@ -238,7 +262,7 @@ const Timeline: React.FC<Props> = ({
}) => (fetchedNoticeHeight.value = height)} }) => (fetchedNoticeHeight.value = height)}
> >
<CustomText <CustomText
fontStyle='M' fontStyle='S'
style={{ color: colors.primaryDefault }} style={{ color: colors.primaryDefault }}
children={ children={
fetchedCount !== null fetchedCount !== null