mirror of
https://github.com/tooot-app/app
synced 2024-12-21 23:24:29 +01:00
Added a button to fetch latest toot on load
This commit is contained in:
parent
8b3ca21ac9
commit
09bc6c30af
@ -1,3 +1,4 @@
|
|||||||
Enjoy toooting! This version includes following improvements and fixes:
|
Enjoy toooting! This version includes following improvements and fixes:
|
||||||
- Supports mute duration
|
- Supports mute duration
|
||||||
- Long press to copy toot
|
- Long press to copy toot
|
||||||
|
- Button to fetch latest on load
|
@ -1,4 +1,5 @@
|
|||||||
tooot-ing愉快!此版本包括以下改进和修复:
|
tooot-ing愉快!此版本包括以下改进和修复:
|
||||||
- 新增neodb.social演出卡片
|
- 新增neodb.social演出卡片
|
||||||
- 支持选择隐藏用户时限
|
- 支持选择隐藏用户时限
|
||||||
- 长按复制嘟文
|
- 长按复制嘟文
|
||||||
|
- 新增获取最新嘟文按钮
|
@ -1,3 +1,4 @@
|
|||||||
|
import Icon from '@components/Icon'
|
||||||
import ComponentSeparator from '@components/Separator'
|
import ComponentSeparator from '@components/Separator'
|
||||||
import CustomText from '@components/Text'
|
import CustomText from '@components/Text'
|
||||||
import TimelineDefault from '@components/Timeline/Default'
|
import TimelineDefault from '@components/Timeline/Default'
|
||||||
@ -10,12 +11,20 @@ import {
|
|||||||
setAccountStorage,
|
setAccountStorage,
|
||||||
useGlobalStorageListener
|
useGlobalStorageListener
|
||||||
} from '@utils/storage/actions'
|
} from '@utils/storage/actions'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import { throttle } from 'lodash'
|
import { throttle } from 'lodash'
|
||||||
import React, { RefObject, useCallback, useEffect, useRef, useState } from 'react'
|
import React, { RefObject, useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { FlatList, FlatListProps, Platform, RefreshControl } from 'react-native'
|
import {
|
||||||
|
FlatList,
|
||||||
|
FlatListProps,
|
||||||
|
Platform,
|
||||||
|
Pressable,
|
||||||
|
RefreshControl,
|
||||||
|
StyleProp,
|
||||||
|
ViewStyle
|
||||||
|
} from 'react-native'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
Easing,
|
Easing,
|
||||||
runOnJS,
|
runOnJS,
|
||||||
@ -127,6 +136,20 @@ const Timeline: React.FC<Props> = ({
|
|||||||
transform: [{ translateY: fetchedNoticeTop.value }]
|
transform: [{ translateY: fetchedNoticeTop.value }]
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
const refetchedNoticeAnimate = useAnimatedStyle(() => ({
|
||||||
|
transform: [
|
||||||
|
{
|
||||||
|
translateY: withSequence(
|
||||||
|
withTiming(0),
|
||||||
|
withDelay(
|
||||||
|
3000,
|
||||||
|
withTiming(fetchedNoticeHeight.value + 32, { easing: Easing.out(Easing.ease) })
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}))
|
||||||
|
|
||||||
const scrollY = useSharedValue(0)
|
const scrollY = useSharedValue(0)
|
||||||
const fetchingType = useSharedValue<0 | 1 | 2>(0)
|
const fetchingType = useSharedValue<0 | 1 | 2>(0)
|
||||||
|
|
||||||
@ -169,10 +192,9 @@ const Timeline: React.FC<Props> = ({
|
|||||||
throttle(() => {
|
throttle(() => {
|
||||||
if (readMarker) {
|
if (readMarker) {
|
||||||
const currentMarker = getAccountStorage.string(readMarker) || '0'
|
const currentMarker = getAccountStorage.string(readMarker) || '0'
|
||||||
|
// setAccountStorage([{ key: readMarker, value: '108425743226508521' }])
|
||||||
if (latestMarker.current > currentMarker) {
|
if (latestMarker.current > currentMarker) {
|
||||||
setAccountStorage([{ key: readMarker, value: latestMarker.current }])
|
setAccountStorage([{ key: readMarker, value: latestMarker.current }])
|
||||||
} else {
|
|
||||||
// setAccountStorage([{ key: readMarker, value: '105250709762254246' }])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 1000 * 15),
|
}, 1000 * 15),
|
||||||
@ -242,6 +264,18 @@ const Timeline: React.FC<Props> = ({
|
|||||||
flRef.current?.scrollToOffset({ offset: 0, animated: false })
|
flRef.current?.scrollToOffset({ offset: 0, animated: false })
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const noticeDefaults: StyleProp<Animated.AnimateStyle<StyleProp<ViewStyle>>> = {
|
||||||
|
position: 'absolute',
|
||||||
|
alignSelf: 'center',
|
||||||
|
borderRadius: 99,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: colors.backgroundDefault,
|
||||||
|
shadowColor: colors.primaryDefault,
|
||||||
|
shadowOffset: { width: 0, height: 0 },
|
||||||
|
shadowOpacity: theme === 'light' ? 0.16 : 0.24
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TimelineRefresh
|
<TimelineRefresh
|
||||||
@ -286,42 +320,78 @@ const Timeline: React.FC<Props> = ({
|
|||||||
{...customProps}
|
{...customProps}
|
||||||
/>
|
/>
|
||||||
{!disableRefresh ? (
|
{!disableRefresh ? (
|
||||||
<Animated.View
|
<>
|
||||||
style={[
|
<Animated.View
|
||||||
{
|
style={[
|
||||||
position: 'absolute',
|
{
|
||||||
alignSelf: 'center',
|
top: -fetchedNoticeHeight.value - 16,
|
||||||
top: -fetchedNoticeHeight.value - 16,
|
paddingVertical: StyleConstants.Spacing.S,
|
||||||
paddingVertical: StyleConstants.Spacing.S,
|
paddingHorizontal: StyleConstants.Spacing.M,
|
||||||
paddingHorizontal: StyleConstants.Spacing.M,
|
...noticeDefaults
|
||||||
backgroundColor: colors.backgroundDefault,
|
},
|
||||||
shadowColor: colors.primaryDefault,
|
fetchedNoticeAnimate
|
||||||
shadowOffset: { width: 0, height: 0 },
|
]}
|
||||||
shadowOpacity: theme === 'light' ? 0.16 : 0.24,
|
onLayout={({
|
||||||
borderRadius: 99,
|
nativeEvent: {
|
||||||
justifyContent: 'center',
|
layout: { height }
|
||||||
alignItems: 'center'
|
}
|
||||||
},
|
}) => (fetchedNoticeHeight.value = height)}
|
||||||
fetchedNoticeAnimate
|
>
|
||||||
]}
|
<CustomText
|
||||||
onLayout={({
|
fontStyle='S'
|
||||||
nativeEvent: {
|
style={{ color: colors.primaryDefault }}
|
||||||
layout: { height }
|
children={
|
||||||
}
|
fetchedCount !== null
|
||||||
}) => (fetchedNoticeHeight.value = height)}
|
? fetchedCount > 0
|
||||||
>
|
? t('refresh.fetched.found', { count: fetchedCount })
|
||||||
<CustomText
|
: t('refresh.fetched.none')
|
||||||
fontStyle='S'
|
: t('refresh.fetching')
|
||||||
style={{ color: colors.primaryDefault }}
|
}
|
||||||
children={
|
/>
|
||||||
fetchedCount !== null
|
</Animated.View>
|
||||||
? fetchedCount > 0
|
{readMarker ? (
|
||||||
? t('refresh.fetched.found', { count: fetchedCount })
|
<Animated.View
|
||||||
: t('refresh.fetched.none')
|
style={[
|
||||||
: t('refresh.fetching')
|
{
|
||||||
}
|
bottom: 16,
|
||||||
/>
|
borderColor: colors.primaryDefault,
|
||||||
</Animated.View>
|
borderWidth: 0.5,
|
||||||
|
...noticeDefaults
|
||||||
|
},
|
||||||
|
refetchedNoticeAnimate
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Pressable
|
||||||
|
style={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: StyleConstants.Spacing.S,
|
||||||
|
paddingVertical: StyleConstants.Spacing.S,
|
||||||
|
paddingHorizontal: StyleConstants.Spacing.M
|
||||||
|
}}
|
||||||
|
onPress={async () => {
|
||||||
|
if (readMarker) {
|
||||||
|
setAccountStorage([{ key: readMarker, value: undefined }])
|
||||||
|
}
|
||||||
|
await refetch()
|
||||||
|
setTimeout(() => flRef.current?.scrollToOffset({ offset: 0 }), 50)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CustomText
|
||||||
|
fontStyle='M'
|
||||||
|
style={{ color: colors.primaryDefault }}
|
||||||
|
children={t('refresh.refetch')}
|
||||||
|
/>
|
||||||
|
<Icon
|
||||||
|
name='log-in'
|
||||||
|
color={colors.primaryDefault}
|
||||||
|
size={StyleConstants.Font.Size.M}
|
||||||
|
style={{ transform: [{ rotate: '-90deg' }] }}
|
||||||
|
/>
|
||||||
|
</Pressable>
|
||||||
|
</Animated.View>
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user