mirror of
https://github.com/tooot-app/app
synced 2025-04-23 22:57:23 +02:00
Retry refresh
This commit is contained in:
parent
1ee7dd920d
commit
c47d4cb4c4
@ -50,14 +50,12 @@ const Timeline: React.FC<Props> = ({
|
|||||||
status,
|
status,
|
||||||
data,
|
data,
|
||||||
refetch,
|
refetch,
|
||||||
isFetching,
|
|
||||||
isSuccess,
|
isSuccess,
|
||||||
hasPreviousPage,
|
hasPreviousPage,
|
||||||
fetchPreviousPage,
|
fetchPreviousPage,
|
||||||
isFetchingPreviousPage,
|
isFetchingPreviousPage,
|
||||||
hasNextPage,
|
hasNextPage,
|
||||||
fetchNextPage,
|
fetchNextPage
|
||||||
isFetchingNextPage
|
|
||||||
} = useInfiniteQuery(queryKey, timelineFetch, {
|
} = useInfiniteQuery(queryKey, timelineFetch, {
|
||||||
getPreviousPageParam: firstPage => {
|
getPreviousPageParam: firstPage => {
|
||||||
return firstPage.toots.length
|
return firstPage.toots.length
|
||||||
@ -67,7 +65,7 @@ const Timeline: React.FC<Props> = ({
|
|||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
},
|
},
|
||||||
getNextPageParam: (lastPage, all) => {
|
getNextPageParam: lastPage => {
|
||||||
return lastPage.toots.length
|
return lastPage.toots.length
|
||||||
? {
|
? {
|
||||||
direction: 'next',
|
direction: 'next',
|
||||||
@ -96,8 +94,8 @@ const Timeline: React.FC<Props> = ({
|
|||||||
}
|
}
|
||||||
}, [isSuccess])
|
}, [isSuccess])
|
||||||
|
|
||||||
const flKeyExtrator = useCallback(({ id }) => id, [])
|
const keyExtractor = useCallback(({ id }) => id, [])
|
||||||
const flRenderItem = useCallback(
|
const renderItem = useCallback(
|
||||||
({ item, index }) => {
|
({ item, index }) => {
|
||||||
switch (page) {
|
switch (page) {
|
||||||
case 'Conversations':
|
case 'Conversations':
|
||||||
@ -123,7 +121,7 @@ const Timeline: React.FC<Props> = ({
|
|||||||
},
|
},
|
||||||
[flattenPinnedLength[0]]
|
[flattenPinnedLength[0]]
|
||||||
)
|
)
|
||||||
const flItemSeparatorComponent = useCallback(
|
const ItemSeparatorComponent = useCallback(
|
||||||
({ leadingItem }) => (
|
({ leadingItem }) => (
|
||||||
<TimelineSeparator
|
<TimelineSeparator
|
||||||
{...(toot && toot.id === leadingItem.id && { highlighted: true })}
|
{...(toot && toot.id === leadingItem.id && { highlighted: true })}
|
||||||
@ -135,27 +133,19 @@ const Timeline: React.FC<Props> = ({
|
|||||||
() => <TimelineEmpty status={status} refetch={refetch} />,
|
() => <TimelineEmpty status={status} refetch={refetch} />,
|
||||||
[status]
|
[status]
|
||||||
)
|
)
|
||||||
const flOnRefresh = useCallback(() => {
|
const onEndReached = useCallback(() => fetchNextPage(), [])
|
||||||
!disableRefresh &&
|
const ListFooterComponent = useCallback(
|
||||||
(hasPreviousPage
|
() => <TimelineEnd hasNextPage={hasNextPage} />,
|
||||||
? fetchPreviousPage()
|
|
||||||
: !isFetching
|
|
||||||
? refetch()
|
|
||||||
: undefined)
|
|
||||||
}, [hasPreviousPage, isFetching])
|
|
||||||
const flOnEndReach = useCallback(() => !disableRefresh && fetchNextPage(), [])
|
|
||||||
const flFooter = useCallback(
|
|
||||||
() => (!disableRefresh ? <TimelineEnd hasNextPage={hasNextPage} /> : null),
|
|
||||||
[hasNextPage]
|
[hasNextPage]
|
||||||
)
|
)
|
||||||
const flRefreshControl = useMemo(
|
const refreshControl = useMemo(
|
||||||
() => (
|
() => (
|
||||||
<RefreshControl
|
<RefreshControl
|
||||||
refreshing={isFetchingPreviousPage || isFetching}
|
refreshing={isFetchingPreviousPage}
|
||||||
onRefresh={flOnRefresh}
|
onRefresh={() => fetchPreviousPage()}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
[isFetchingPreviousPage, isFetching]
|
[isFetchingPreviousPage]
|
||||||
)
|
)
|
||||||
const onScrollToIndexFailed = useCallback(error => {
|
const onScrollToIndexFailed = useCallback(error => {
|
||||||
const offset = error.averageItemLength * error.index
|
const offset = error.averageItemLength * error.index
|
||||||
@ -177,14 +167,14 @@ const Timeline: React.FC<Props> = ({
|
|||||||
initialNumToRender={5}
|
initialNumToRender={5}
|
||||||
maxToRenderPerBatch={5}
|
maxToRenderPerBatch={5}
|
||||||
style={styles.flatList}
|
style={styles.flatList}
|
||||||
renderItem={flRenderItem}
|
renderItem={renderItem}
|
||||||
onEndReached={flOnEndReach}
|
onEndReached={onEndReached}
|
||||||
keyExtractor={flKeyExtrator}
|
keyExtractor={keyExtractor}
|
||||||
ListFooterComponent={flFooter}
|
onEndReachedThreshold={0.75}
|
||||||
refreshControl={flRefreshControl}
|
ListFooterComponent={ListFooterComponent}
|
||||||
ListEmptyComponent={flItemEmptyComponent}
|
ListEmptyComponent={flItemEmptyComponent}
|
||||||
ItemSeparatorComponent={flItemSeparatorComponent}
|
{...(!disableRefresh && { refreshControl })}
|
||||||
onEndReachedThreshold={!disableRefresh ? 0.75 : null}
|
ItemSeparatorComponent={ItemSeparatorComponent}
|
||||||
{...(toot && isSuccess && { onScrollToIndexFailed })}
|
{...(toot && isSuccess && { onScrollToIndexFailed })}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -17,7 +17,7 @@ const TimelineAvatar: React.FC<Props> = ({ queryKey, account }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Pressable style={styles.avatar} onPress={onPress}>
|
<Pressable style={styles.avatar} onPress={onPress}>
|
||||||
<Image source={{ uri: account.avatar }} style={styles.image} />
|
<Image source={{ uri: account.avatar_static }} style={styles.image} />
|
||||||
</Pressable>
|
</Pressable>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useRef, useState } from 'react'
|
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 { useSelector } from 'react-redux'
|
||||||
|
|
||||||
import { getLocalUrl } from '@utils/slices/instancesSlice'
|
import { getLocalUrl } from '@utils/slices/instancesSlice'
|
||||||
@ -14,6 +14,7 @@ import { AccountState } from '../Shared/Account'
|
|||||||
import AccountNav from '../Shared/Account/Nav'
|
import AccountNav from '../Shared/Account/Nav'
|
||||||
|
|
||||||
const ScreenMeRoot: React.FC = () => {
|
const ScreenMeRoot: React.FC = () => {
|
||||||
|
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
|
||||||
const localRegistered = useSelector(getLocalUrl)
|
const localRegistered = useSelector(getLocalUrl)
|
||||||
|
|
||||||
const scrollRef = useRef<ScrollView>(null)
|
const scrollRef = useRef<ScrollView>(null)
|
||||||
|
@ -28,7 +28,7 @@ const MyInfo: React.FC<Props> = ({ setData }) => {
|
|||||||
account={data}
|
account={data}
|
||||||
limitHeight
|
limitHeight
|
||||||
/>
|
/>
|
||||||
<AccountInformation account={data} />
|
<AccountInformation account={data} disableActions />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useReducer, useRef, useState } from 'react'
|
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 { useQuery } from 'react-query'
|
||||||
import { accountFetch } from '@utils/fetches/accountFetch'
|
import { accountFetch } from '@utils/fetches/accountFetch'
|
||||||
@ -73,10 +73,10 @@ const ScreenSharedAccount: React.FC<Props> = ({
|
|||||||
},
|
},
|
||||||
navigation
|
navigation
|
||||||
}) => {
|
}) => {
|
||||||
|
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
|
||||||
const localAccountId = useSelector(getLocalAccountId)
|
const localAccountId = useSelector(getLocalAccountId)
|
||||||
const { data } = useQuery(['Account', { id: account.id }], accountFetch)
|
const { data } = useQuery(['Account', { id: account.id }], accountFetch)
|
||||||
|
|
||||||
// const stateRelationships = useSelector(relationshipsState)
|
|
||||||
const scrollY = useRef(new Animated.Value(0)).current
|
const scrollY = useRef(new Animated.Value(0)).current
|
||||||
const [accountState, accountDispatch] = useReducer(
|
const [accountState, accountDispatch] = useReducer(
|
||||||
accountReducer,
|
accountReducer,
|
||||||
@ -104,11 +104,14 @@ const ScreenSharedAccount: React.FC<Props> = ({
|
|||||||
scrollY={scrollY}
|
scrollY={scrollY}
|
||||||
account={data}
|
account={data}
|
||||||
/>
|
/>
|
||||||
|
{accountState.informationLayout?.height &&
|
||||||
|
accountState.informationLayout.y ? (
|
||||||
<AccountSegmentedControl
|
<AccountSegmentedControl
|
||||||
accountState={accountState}
|
accountState={accountState}
|
||||||
accountDispatch={accountDispatch}
|
accountDispatch={accountDispatch}
|
||||||
scrollY={scrollY}
|
scrollY={scrollY}
|
||||||
/>
|
/>
|
||||||
|
) : null}
|
||||||
<ScrollView
|
<ScrollView
|
||||||
bounces={false}
|
bounces={false}
|
||||||
onScroll={Animated.event(
|
onScroll={Animated.event(
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { Dispatch, useEffect, useRef, useState } from 'react'
|
import React, { Dispatch, useEffect, useState } from 'react'
|
||||||
import { Animated, Dimensions, Image, StyleSheet } from 'react-native'
|
import { Dimensions, Image, StyleSheet, View } from 'react-native'
|
||||||
import { AccountAction, AccountState } from '../Account'
|
import { AccountAction, AccountState } from '../Account'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
@ -15,19 +15,14 @@ const AccountHeader: React.FC<Props> = ({
|
|||||||
account,
|
account,
|
||||||
limitHeight = false
|
limitHeight = false
|
||||||
}) => {
|
}) => {
|
||||||
const [imageShown, setImageShown] = useState(true)
|
const [ratio, setRatio] = useState(accountState.headerRatio)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (account?.header) {
|
if (
|
||||||
if (account.header.includes('/headers/original/missing.png')) {
|
account?.header &&
|
||||||
animateNewSize(accountState.headerRatio)
|
!account.header.includes('/headers/original/missing.png')
|
||||||
} else {
|
) {
|
||||||
if (account.header !== account.header_static) {
|
Image.getSize(account.header, (width, height) => {
|
||||||
setImageShown(false)
|
|
||||||
}
|
|
||||||
Image.getSize(
|
|
||||||
account.header,
|
|
||||||
(width, height) => {
|
|
||||||
if (!limitHeight) {
|
if (!limitHeight) {
|
||||||
accountDispatch &&
|
accountDispatch &&
|
||||||
accountDispatch({
|
accountDispatch({
|
||||||
@ -35,42 +30,17 @@ const AccountHeader: React.FC<Props> = ({
|
|||||||
payload: height / width
|
payload: height / width
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
animateNewSize(
|
setRatio(limitHeight ? accountState.headerRatio : height / width)
|
||||||
limitHeight ? accountState.headerRatio : height / width
|
})
|
||||||
)
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
animateNewSize(accountState.headerRatio)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [account])
|
}, [account])
|
||||||
|
|
||||||
const theImage = imageShown ? (
|
|
||||||
<Image source={{ uri: account?.header }} style={styles.image} />
|
|
||||||
) : null
|
|
||||||
|
|
||||||
const windowWidth = Dimensions.get('window').width
|
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 (
|
return (
|
||||||
<Animated.View style={[styles.imageContainer, { height: imageHeight }]}>
|
<View style={[styles.imageContainer, { height: windowWidth * ratio }]}>
|
||||||
{theImage}
|
<Image source={{ uri: account?.header }} style={styles.image} />
|
||||||
</Animated.View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,9 +49,14 @@ const fireMutation = async ({
|
|||||||
export interface Props {
|
export interface Props {
|
||||||
accountDispatch?: Dispatch<AccountAction>
|
accountDispatch?: Dispatch<AccountAction>
|
||||||
account: Mastodon.Account | undefined
|
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 navigation = useNavigation()
|
||||||
const { t } = useTranslation('sharedAccount')
|
const { t } = useTranslation('sharedAccount')
|
||||||
const { theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
@ -165,6 +170,7 @@ const AccountInformation: React.FC<Props> = ({ accountDispatch, account }) => {
|
|||||||
onLoadEnd={() => setAvatarLoaded(true)}
|
onLoadEnd={() => setAvatarLoaded(true)}
|
||||||
/>
|
/>
|
||||||
</ShimmerPlaceholder>
|
</ShimmerPlaceholder>
|
||||||
|
{!disableActions && (
|
||||||
<View style={styles.actions}>
|
<View style={styles.actions}>
|
||||||
<ButtonRow
|
<ButtonRow
|
||||||
icon='mail'
|
icon='mail'
|
||||||
@ -181,6 +187,7 @@ const AccountInformation: React.FC<Props> = ({ accountDispatch, account }) => {
|
|||||||
/>
|
/>
|
||||||
{followingButton}
|
{followingButton}
|
||||||
</View>
|
</View>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<ShimmerPlaceholder
|
<ShimmerPlaceholder
|
||||||
|
@ -35,7 +35,8 @@ const AccountSegmentedControl: React.FC<Props> = ({
|
|||||||
(accountState.informationLayout?.height || 0) +
|
(accountState.informationLayout?.height || 0) +
|
||||||
headerHeight
|
headerHeight
|
||||||
],
|
],
|
||||||
extrapolate: 'clamp'
|
extrapolate: 'clamp',
|
||||||
|
easing: undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
Alert,
|
Alert,
|
||||||
Keyboard,
|
Keyboard,
|
||||||
KeyboardAvoidingView,
|
KeyboardAvoidingView,
|
||||||
|
LayoutAnimation,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
Text,
|
Text,
|
||||||
TextInput
|
TextInput
|
||||||
@ -330,6 +331,7 @@ export interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Compose: React.FC<Props> = ({ route: { params }, navigation }) => {
|
const Compose: React.FC<Props> = ({ route: { params }, navigation }) => {
|
||||||
|
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
|
||||||
const { theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user