Retry refresh

This commit is contained in:
Zhiyuan Zheng 2020-12-21 22:58:53 +01:00
parent 1ee7dd920d
commit c47d4cb4c4
No known key found for this signature in database
GPG Key ID: 078A93AB607D85E0
9 changed files with 80 additions and 106 deletions

View File

@ -50,14 +50,12 @@ const Timeline: React.FC<Props> = ({
status,
data,
refetch,
isFetching,
isSuccess,
hasPreviousPage,
fetchPreviousPage,
isFetchingPreviousPage,
hasNextPage,
fetchNextPage,
isFetchingNextPage
fetchNextPage
} = useInfiniteQuery(queryKey, timelineFetch, {
getPreviousPageParam: firstPage => {
return firstPage.toots.length
@ -67,7 +65,7 @@ const Timeline: React.FC<Props> = ({
}
: undefined
},
getNextPageParam: (lastPage, all) => {
getNextPageParam: lastPage => {
return lastPage.toots.length
? {
direction: 'next',
@ -96,8 +94,8 @@ const Timeline: React.FC<Props> = ({
}
}, [isSuccess])
const flKeyExtrator = useCallback(({ id }) => id, [])
const flRenderItem = useCallback(
const keyExtractor = useCallback(({ id }) => id, [])
const renderItem = useCallback(
({ item, index }) => {
switch (page) {
case 'Conversations':
@ -123,7 +121,7 @@ const Timeline: React.FC<Props> = ({
},
[flattenPinnedLength[0]]
)
const flItemSeparatorComponent = useCallback(
const ItemSeparatorComponent = useCallback(
({ leadingItem }) => (
<TimelineSeparator
{...(toot && toot.id === leadingItem.id && { highlighted: true })}
@ -135,27 +133,19 @@ const Timeline: React.FC<Props> = ({
() => <TimelineEmpty status={status} refetch={refetch} />,
[status]
)
const flOnRefresh = useCallback(() => {
!disableRefresh &&
(hasPreviousPage
? fetchPreviousPage()
: !isFetching
? refetch()
: undefined)
}, [hasPreviousPage, isFetching])
const flOnEndReach = useCallback(() => !disableRefresh && fetchNextPage(), [])
const flFooter = useCallback(
() => (!disableRefresh ? <TimelineEnd hasNextPage={hasNextPage} /> : null),
const onEndReached = useCallback(() => fetchNextPage(), [])
const ListFooterComponent = useCallback(
() => <TimelineEnd hasNextPage={hasNextPage} />,
[hasNextPage]
)
const flRefreshControl = useMemo(
const refreshControl = useMemo(
() => (
<RefreshControl
refreshing={isFetchingPreviousPage || isFetching}
onRefresh={flOnRefresh}
refreshing={isFetchingPreviousPage}
onRefresh={() => fetchPreviousPage()}
/>
),
[isFetchingPreviousPage, isFetching]
[isFetchingPreviousPage]
)
const onScrollToIndexFailed = useCallback(error => {
const offset = error.averageItemLength * error.index
@ -177,14 +167,14 @@ const Timeline: React.FC<Props> = ({
initialNumToRender={5}
maxToRenderPerBatch={5}
style={styles.flatList}
renderItem={flRenderItem}
onEndReached={flOnEndReach}
keyExtractor={flKeyExtrator}
ListFooterComponent={flFooter}
refreshControl={flRefreshControl}
renderItem={renderItem}
onEndReached={onEndReached}
keyExtractor={keyExtractor}
onEndReachedThreshold={0.75}
ListFooterComponent={ListFooterComponent}
ListEmptyComponent={flItemEmptyComponent}
ItemSeparatorComponent={flItemSeparatorComponent}
onEndReachedThreshold={!disableRefresh ? 0.75 : null}
{...(!disableRefresh && { refreshControl })}
ItemSeparatorComponent={ItemSeparatorComponent}
{...(toot && isSuccess && { onScrollToIndexFailed })}
/>
)

View File

@ -17,7 +17,7 @@ const TimelineAvatar: React.FC<Props> = ({ queryKey, account }) => {
return (
<Pressable style={styles.avatar} onPress={onPress}>
<Image source={{ uri: account.avatar }} style={styles.image} />
<Image source={{ uri: account.avatar_static }} style={styles.image} />
</Pressable>
)
}

View File

@ -1,5 +1,5 @@
import React, { useRef, useState } from 'react'
import { Animated, ScrollView } from 'react-native'
import { Animated, LayoutAnimation, ScrollView } from 'react-native'
import { useSelector } from 'react-redux'
import { getLocalUrl } from '@utils/slices/instancesSlice'
@ -14,6 +14,7 @@ import { AccountState } from '../Shared/Account'
import AccountNav from '../Shared/Account/Nav'
const ScreenMeRoot: React.FC = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
const localRegistered = useSelector(getLocalUrl)
const scrollRef = useRef<ScrollView>(null)

View File

@ -28,7 +28,7 @@ const MyInfo: React.FC<Props> = ({ setData }) => {
account={data}
limitHeight
/>
<AccountInformation account={data} />
<AccountInformation account={data} disableActions />
</>
)
}

View File

@ -1,5 +1,5 @@
import React, { useEffect, useReducer, useRef, useState } from 'react'
import { Animated, ScrollView } from 'react-native'
import { Animated, LayoutAnimation, ScrollView } from 'react-native'
import { useQuery } from 'react-query'
import { accountFetch } from '@utils/fetches/accountFetch'
@ -73,10 +73,10 @@ const ScreenSharedAccount: React.FC<Props> = ({
},
navigation
}) => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
const localAccountId = useSelector(getLocalAccountId)
const { data } = useQuery(['Account', { id: account.id }], accountFetch)
// const stateRelationships = useSelector(relationshipsState)
const scrollY = useRef(new Animated.Value(0)).current
const [accountState, accountDispatch] = useReducer(
accountReducer,
@ -104,11 +104,14 @@ const ScreenSharedAccount: React.FC<Props> = ({
scrollY={scrollY}
account={data}
/>
<AccountSegmentedControl
accountState={accountState}
accountDispatch={accountDispatch}
scrollY={scrollY}
/>
{accountState.informationLayout?.height &&
accountState.informationLayout.y ? (
<AccountSegmentedControl
accountState={accountState}
accountDispatch={accountDispatch}
scrollY={scrollY}
/>
) : null}
<ScrollView
bounces={false}
onScroll={Animated.event(

View File

@ -1,5 +1,5 @@
import React, { Dispatch, useEffect, useRef, useState } from 'react'
import { Animated, Dimensions, Image, StyleSheet } from 'react-native'
import React, { Dispatch, useEffect, useState } from 'react'
import { Dimensions, Image, StyleSheet, View } from 'react-native'
import { AccountAction, AccountState } from '../Account'
export interface Props {
@ -15,62 +15,32 @@ const AccountHeader: React.FC<Props> = ({
account,
limitHeight = false
}) => {
const [imageShown, setImageShown] = useState(true)
const [ratio, setRatio] = useState(accountState.headerRatio)
useEffect(() => {
if (account?.header) {
if (account.header.includes('/headers/original/missing.png')) {
animateNewSize(accountState.headerRatio)
} else {
if (account.header !== account.header_static) {
setImageShown(false)
if (
account?.header &&
!account.header.includes('/headers/original/missing.png')
) {
Image.getSize(account.header, (width, height) => {
if (!limitHeight) {
accountDispatch &&
accountDispatch({
type: 'headerRatio',
payload: height / width
})
}
Image.getSize(
account.header,
(width, height) => {
if (!limitHeight) {
accountDispatch &&
accountDispatch({
type: 'headerRatio',
payload: height / width
})
}
animateNewSize(
limitHeight ? accountState.headerRatio : height / width
)
},
() => {
animateNewSize(accountState.headerRatio)
}
)
}
setRatio(limitHeight ? accountState.headerRatio : height / width)
})
}
}, [account])
const theImage = imageShown ? (
<Image source={{ uri: account?.header }} style={styles.image} />
) : null
const windowWidth = Dimensions.get('window').width
const imageHeight = useRef(
new Animated.Value(windowWidth * accountState.headerRatio)
).current
const animateNewSize = (ratio: number) => {
Animated.timing(imageHeight, {
toValue: windowWidth * ratio,
duration: 350,
useNativeDriver: false
}).start(({ finished }) => {
if (finished) {
setImageShown(true)
}
})
}
return (
<Animated.View style={[styles.imageContainer, { height: imageHeight }]}>
{theImage}
</Animated.View>
<View style={[styles.imageContainer, { height: windowWidth * ratio }]}>
<Image source={{ uri: account?.header }} style={styles.image} />
</View>
)
}

View File

@ -49,9 +49,14 @@ const fireMutation = async ({
export interface Props {
accountDispatch?: Dispatch<AccountAction>
account: Mastodon.Account | undefined
disableActions?: boolean
}
const AccountInformation: React.FC<Props> = ({ accountDispatch, account }) => {
const AccountInformation: React.FC<Props> = ({
accountDispatch,
account,
disableActions = false
}) => {
const navigation = useNavigation()
const { t } = useTranslation('sharedAccount')
const { theme } = useTheme()
@ -165,22 +170,24 @@ const AccountInformation: React.FC<Props> = ({ accountDispatch, account }) => {
onLoadEnd={() => setAvatarLoaded(true)}
/>
</ShimmerPlaceholder>
<View style={styles.actions}>
<ButtonRow
icon='mail'
onPress={() =>
navigation.navigate(getCurrentTab(navigation), {
screen: 'Screen-Shared-Compose',
params: {
type: 'conversation',
incomingStatus: { account }
}
})
}
style={{ marginRight: StyleConstants.Spacing.S }}
/>
{followingButton}
</View>
{!disableActions && (
<View style={styles.actions}>
<ButtonRow
icon='mail'
onPress={() =>
navigation.navigate(getCurrentTab(navigation), {
screen: 'Screen-Shared-Compose',
params: {
type: 'conversation',
incomingStatus: { account }
}
})
}
style={{ marginRight: StyleConstants.Spacing.S }}
/>
{followingButton}
</View>
)}
</View>
<ShimmerPlaceholder

View File

@ -35,7 +35,8 @@ const AccountSegmentedControl: React.FC<Props> = ({
(accountState.informationLayout?.height || 0) +
headerHeight
],
extrapolate: 'clamp'
extrapolate: 'clamp',
easing: undefined
})
return (

View File

@ -13,6 +13,7 @@ import {
Alert,
Keyboard,
KeyboardAvoidingView,
LayoutAnimation,
StyleSheet,
Text,
TextInput
@ -330,6 +331,7 @@ export interface Props {
}
const Compose: React.FC<Props> = ({ route: { params }, navigation }) => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
const { theme } = useTheme()
const queryClient = useQueryClient()