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,
useAnimatedReaction,
useAnimatedStyle,
useDerivedValue,
useSharedValue,
withTiming
} from 'react-native-reanimated'
@ -28,10 +27,10 @@ import Animated, {
export interface Props {
flRef: RefObject<FlatList<any>>
queryKey: QueryKeyTimeline
fetchingActive: React.MutableRefObject<boolean>
isFetchingPrev: SharedValue<boolean>
setFetchedCount: React.Dispatch<React.SetStateAction<number | null>>
scrollY: Animated.SharedValue<number>
fetchingType: Animated.SharedValue<0 | 1 | 2>
scrollY: SharedValue<number>
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<Props> = ({
flRef,
queryKey,
fetchingActive,
isFetchingPrev,
setFetchedCount,
scrollY,
fetchingType,
@ -58,20 +57,11 @@ const TimelineRefresh: React.FC<Props> = ({
}
const PREV_PER_BATCH = 1
const prevActive = useRef<boolean>(false)
const prevCache = useRef<(Mastodon.Status | Mastodon.Notification | Mastodon.Conversation)[]>()
const prevStatusId = useRef<Mastodon.Status['id']>()
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<Props> = ({
const arrowStage = useSharedValue(0)
useAnimatedReaction(
() => {
if (fetchingActive.current) {
if (isFetchingPrev.value) {
return false
}
switch (arrowStage.value) {
@ -131,13 +121,12 @@ const TimelineRefresh: React.FC<Props> = ({
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<Props> = ({
>
>(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<Props> = ({
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<Props> = ({
})
.then(async nextLength => {
if (!nextLength) {
prevActive.current = false
isFetchingPrev.value = false
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, {
Easing,
runOnJS,
useAnimatedReaction,
useAnimatedScrollHandler,
useAnimatedStyle,
useDerivedValue,
@ -70,26 +71,44 @@ const Timeline: React.FC<Props> = ({
})
const flRef = useRef<FlatList>(null)
const fetchingActive = useRef<boolean>(false)
const isFetchingPrev = useSharedValue<boolean>(false)
const [fetchedCount, setFetchedCount] = useState<number | null>(null)
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(() => {
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<Props> = ({
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<Props> = ({
<TimelineRefresh
flRef={flRef}
queryKey={queryKey}
fetchingActive={fetchingActive}
isFetchingPrev={isFetchingPrev}
setFetchedCount={setFetchedCount}
scrollY={scrollY}
fetchingType={fetchingType}
@ -238,7 +262,7 @@ const Timeline: React.FC<Props> = ({
}) => (fetchedNoticeHeight.value = height)}
>
<CustomText
fontStyle='M'
fontStyle='S'
style={{ color: colors.primaryDefault }}
children={
fetchedCount !== null