1
0
mirror of https://github.com/tooot-app/app synced 2025-01-26 16:35:17 +01:00

Use simpler Account page

This commit is contained in:
Zhiyuan Zheng 2021-01-15 01:15:27 +01:00
parent d39bc82909
commit 9f4a4e908c
No known key found for this signature in database
GPG Key ID: 078A93AB607D85E0
13 changed files with 105 additions and 247 deletions

View File

@ -9,7 +9,12 @@ import { useScrollToTop } from '@react-navigation/native'
import { localUpdateNotification } from '@utils/slices/instancesSlice'
import { StyleConstants } from '@utils/styles/constants'
import React, { useCallback, useEffect, useMemo, useRef } from 'react'
import { Platform, RefreshControl, StyleSheet } from 'react-native'
import {
FlatListProps,
Platform,
RefreshControl,
StyleSheet
} from 'react-native'
import { FlatList } from 'react-native-gesture-handler'
import { useDispatch } from 'react-redux'
import { QueryKeyTimeline, useTimelineQuery } from '@utils/queryHooks/timeline'
@ -24,6 +29,7 @@ export interface Props {
account?: Mastodon.Account['id']
disableRefresh?: boolean
disableInfinity?: boolean
customProps?: Partial<FlatListProps<any>>
}
const Timeline: React.FC<Props> = ({
@ -33,7 +39,8 @@ const Timeline: React.FC<Props> = ({
toot,
account,
disableRefresh = false,
disableInfinity = false
disableInfinity = false,
customProps
}) => {
const queryKeyParams = {
page,
@ -208,7 +215,6 @@ const Timeline: React.FC<Props> = ({
return (
<FlatList
bounces={!disableRefresh}
ref={flRef}
windowSize={11}
data={flattenData}
@ -230,6 +236,7 @@ const Timeline: React.FC<Props> = ({
// minIndexForVisible: 0,
// autoscrollToTopThreshold: 2
// }}
{...customProps}
/>
)
}

View File

@ -1,19 +1,15 @@
import BottomSheet from '@components/BottomSheet'
import { HeaderRight } from '@components/Header'
import Timeline from '@components/Timelines/Timeline'
import HeaderActionsAccount from '@components/Timelines/Timeline/Shared/HeaderActions/ActionsAccount'
import { useAccountQuery } from '@utils/queryHooks/account'
import { getLocalAccount } from '@utils/slices/instancesSlice'
import React, { useEffect, useReducer, useState } from 'react'
import Animated, {
useAnimatedScrollHandler,
useSharedValue
} from 'react-native-reanimated'
import React, { useCallback, useEffect, useReducer, useState } from 'react'
import { useSharedValue } from 'react-native-reanimated'
import { useSelector } from 'react-redux'
import AccountHeader from './Account/Header'
import AccountInformation from './Account/Information'
import AccountNav from './Account/Nav'
import AccountSegmentedControl from './Account/SegmentedControl'
import AccountToots from './Account/Toots'
import AccountContext from './Account/utils/createContext'
import accountInitialState from './Account/utils/initialState'
import accountReducer from './Account/utils/reducer'
@ -50,26 +46,29 @@ const ScreenSharedAccount: React.FC<SharedAccountProp> = ({
return updateHeaderRight()
}, [])
const onScroll = useAnimatedScrollHandler(event => {
scrollY.value = event.contentOffset.y
})
const onScroll = useCallback(({ nativeEvent }) => {
scrollY.value = nativeEvent.contentOffset.y
}, [])
return (
<AccountContext.Provider value={{ accountState, accountDispatch }}>
<AccountNav scrollY={scrollY} account={data} />
{accountState.informationLayout?.height &&
accountState.informationLayout.y ? (
<AccountSegmentedControl scrollY={scrollY} />
) : null}
<Animated.ScrollView
scrollEventThrottle={16}
showsVerticalScrollIndicator={false}
onScroll={onScroll}
>
<AccountHeader account={data} />
<AccountInformation account={data} />
<AccountToots id={account.id} />
</Animated.ScrollView>
<Timeline
page='Account_Default'
account={account.id}
disableRefresh
customProps={{
onScroll,
scrollEventThrottle: 16,
ListHeaderComponent: (
<>
<AccountHeader account={data} />
<AccountInformation account={data} />
</>
)
}}
/>
<BottomSheet
visible={modalVisible}

View File

@ -43,8 +43,8 @@ const AccountHeader: React.FC<Props> = ({ account, limitHeight = false }) => {
}, [account])
return (
<Animated.View
// source={{ uri: account?.header }}
<Animated.Image
source={{ uri: account?.header }}
style={[styleHeight, { backgroundColor: theme.disabled }]}
/>
)

View File

@ -1,4 +1,5 @@
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { createRef, useCallback, useContext, useEffect } from 'react'
import { Animated, StyleSheet, View } from 'react-native'
import AccountInformationAccount from './Information/Account'
@ -21,7 +22,9 @@ const AccountInformation: React.FC<Props> = ({
account,
ownAccount = false
}) => {
const { theme } = useTheme()
const { accountDispatch } = useContext(AccountContext)
const shimmerAvatarRef = createRef<any>()
const shimmerNameRef = createRef<any>()
const shimmerAccountRef = createRef<any>()
@ -56,7 +59,10 @@ const AccountInformation: React.FC<Props> = ({
)
return (
<View style={styles.base} onLayout={onLayout}>
<View
style={[styles.base, { borderBottomColor: theme.border }]}
onLayout={onLayout}
>
{/* <Text>Moved or not: {account.moved}</Text> */}
<View style={styles.avatarAndActions}>
<AccountInformationAvatar ref={shimmerAvatarRef} account={account} />
@ -99,7 +105,8 @@ const AccountInformation: React.FC<Props> = ({
const styles = StyleSheet.create({
base: {
marginTop: -StyleConstants.Spacing.Global.PagePadding * 3,
padding: StyleConstants.Spacing.Global.PagePadding
padding: StyleConstants.Spacing.Global.PagePadding,
borderBottomWidth: StyleSheet.hairlineWidth
},
avatarAndActions: {
flexDirection: 'row',

View File

@ -23,7 +23,7 @@ const AccountInformationAccount = forwardRef<ShimmerPlaceholder, Props>(
ref={ref}
visible={account?.acct !== undefined}
width={StyleConstants.Font.Size.M * 8}
height={StyleConstants.Font.Size.M}
height={StyleConstants.Font.LineHeight.M}
style={{ marginBottom: StyleConstants.Spacing.L }}
shimmerColors={[theme.shimmerDefault, theme.shimmerHighlight, theme.shimmerDefault]}
>

View File

@ -24,7 +24,7 @@ const AccountInformationCreated = forwardRef<ShimmerPlaceholder, Props>(
ref={ref}
visible={account?.created_at !== undefined}
width={StyleConstants.Font.Size.S * 8}
height={StyleConstants.Font.Size.S}
height={StyleConstants.Font.LineHeight.S}
style={{ marginBottom: StyleConstants.Spacing.M }}
shimmerColors={[theme.shimmerDefault, theme.shimmerHighlight, theme.shimmerDefault]}
>

View File

@ -9,47 +9,52 @@ export interface Props {
account: Mastodon.Account
}
const AccountInformationFields: React.FC<Props> = ({ account }) => {
const { theme } = useTheme()
const AccountInformationFields = React.memo(
({ account }: Props) => {
const { theme } = useTheme()
return (
<View style={[styles.fields, { borderTopColor: theme.border }]}>
{account.fields.map((field, index) => (
<View
key={index}
style={[styles.field, { borderBottomColor: theme.border }]}
>
<View style={[styles.fieldLeft, { borderRightColor: theme.border }]}>
<ParseHTML
content={field.name}
size={'M'}
emojis={account.emojis}
showFullLink
numberOfLines={3}
/>
{field.verified_at ? (
<Icon
name='CheckCircle'
size={StyleConstants.Font.Size.M}
color={theme.primary}
style={styles.fieldCheck}
return (
<View style={[styles.fields, { borderTopColor: theme.border }]}>
{account.fields.map((field, index) => (
<View
key={index}
style={[styles.field, { borderBottomColor: theme.border }]}
>
<View
style={[styles.fieldLeft, { borderRightColor: theme.border }]}
>
<ParseHTML
content={field.name}
size={'M'}
emojis={account.emojis}
showFullLink
numberOfLines={3}
/>
) : null}
{field.verified_at ? (
<Icon
name='CheckCircle'
size={StyleConstants.Font.Size.M}
color={theme.primary}
style={styles.fieldCheck}
/>
) : null}
</View>
<View style={styles.fieldRight}>
<ParseHTML
content={field.value}
size={'M'}
emojis={account.emojis}
showFullLink
numberOfLines={3}
/>
</View>
</View>
<View style={styles.fieldRight}>
<ParseHTML
content={field.value}
size={'M'}
emojis={account.emojis}
showFullLink
numberOfLines={3}
/>
</View>
</View>
))}
</View>
)
}
))}
</View>
)
},
() => true
)
const styles = StyleSheet.create({
fields: {

View File

@ -24,7 +24,7 @@ const AccountInformationName = forwardRef<ShimmerPlaceholder, Props>(
account?.display_name !== undefined || account?.username !== undefined
}
width={StyleConstants.Font.Size.L * 8}
height={StyleConstants.Font.Size.L}
height={StyleConstants.Font.LineHeight.L}
style={styles.name}
shimmerColors={[theme.shimmerDefault, theme.shimmerHighlight, theme.shimmerDefault]}
>

View File

@ -7,13 +7,16 @@ export interface Props {
account: Mastodon.Account
}
const AccountInformationNotes: React.FC<Props> = ({ account }) => {
return (
<View style={styles.note}>
<ParseHTML content={account.note!} size={'M'} emojis={account.emojis} />
</View>
)
}
const AccountInformationNotes = React.memo(
({ account }: Props) => {
return (
<View style={styles.note}>
<ParseHTML content={account.note!} size={'M'} emojis={account.emojis} />
</View>
)
},
() => true
)
const styles = StyleSheet.create({
note: {

View File

@ -40,7 +40,7 @@ const AccountInformationStats = forwardRef<any, Props>(({ account }, ref) => {
ref={ref1}
visible={account !== undefined}
width={StyleConstants.Font.Size.S * 5}
height={StyleConstants.Font.Size.S}
height={StyleConstants.Font.LineHeight.S}
shimmerColors={[theme.shimmerDefault, theme.shimmerHighlight, theme.shimmerDefault]}
>
<Text style={[styles.stat, { color: theme.primary }]}>
@ -53,7 +53,7 @@ const AccountInformationStats = forwardRef<any, Props>(({ account }, ref) => {
ref={ref2}
visible={account !== undefined}
width={StyleConstants.Font.Size.S * 5}
height={StyleConstants.Font.Size.S}
height={StyleConstants.Font.LineHeight.S}
shimmerColors={[theme.shimmerDefault, theme.shimmerHighlight, theme.shimmerDefault]}
>
<Text
@ -75,7 +75,7 @@ const AccountInformationStats = forwardRef<any, Props>(({ account }, ref) => {
ref={ref3}
visible={account !== undefined}
width={StyleConstants.Font.Size.S * 5}
height={StyleConstants.Font.Size.S}
height={StyleConstants.Font.LineHeight.S}
shimmerColors={[theme.shimmerDefault, theme.shimmerHighlight, theme.shimmerDefault]}
>
<Text

View File

@ -1,93 +0,0 @@
import SegmentedControl from '@react-native-community/segmented-control'
import { StyleConstants } from '@root/utils/styles/constants'
import { useTheme } from '@root/utils/styles/ThemeManager'
import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet } from 'react-native'
import Animated, {
Extrapolate,
interpolate,
useAnimatedStyle
} from 'react-native-reanimated'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import AccountContext from './utils/createContext'
export interface Props {
scrollY: Animated.SharedValue<number>
}
const AccountSegmentedControl: React.FC<Props> = ({ scrollY }) => {
const { accountState, accountDispatch } = useContext(AccountContext)
const { t } = useTranslation('sharedAccount')
const { mode, theme } = useTheme()
const headerHeight = useSafeAreaInsets().top + 44
const styleTransform = useAnimatedStyle(() => {
return {
transform: [
{
translateY: interpolate(
scrollY.value,
[
0,
(accountState.informationLayout?.y || 0) +
(accountState.informationLayout?.height || 0) -
headerHeight
],
[
0,
-(accountState.informationLayout?.y || 0) -
(accountState.informationLayout?.height || 0) +
headerHeight
],
Extrapolate.CLAMP
)
}
]
}
})
return (
<Animated.View
style={[
styles.base,
styleTransform,
{
top:
(accountState.informationLayout?.y || 0) +
(accountState.informationLayout?.height || 0),
borderTopColor: theme.border,
backgroundColor: theme.background
}
]}
>
<SegmentedControl
values={[
t('content.segments.left'),
t('content.segments.middle'),
t('content.segments.right')
]}
selectedIndex={accountState.segmentedIndex}
onChange={({ nativeEvent }) =>
accountDispatch({
type: 'segmentedIndex',
payload: nativeEvent.selectedSegmentIndex
})
}
appearance={mode}
/>
</Animated.View>
)
}
const styles = StyleSheet.create({
base: {
...StyleSheet.absoluteFillObject,
zIndex: 99,
borderTopWidth: StyleSheet.hairlineWidth,
padding: StyleConstants.Spacing.Global.PagePadding,
height: 33 + StyleConstants.Spacing.Global.PagePadding * 2
}
})
export default React.memo(AccountSegmentedControl, () => true)

View File

@ -1,70 +0,0 @@
import Timeline from '@components/Timelines/Timeline'
import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs'
import { StyleConstants } from '@utils/styles/constants'
import React, { useCallback, useContext } from 'react'
import { Dimensions, StyleSheet } from 'react-native'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import { TabView } from 'react-native-tab-view'
import ViewPagerAdapter from 'react-native-tab-view-viewpager-adapter'
import AccountContext from './utils/createContext'
export interface Props {
id: Mastodon.Account['id']
}
const AccountToots: React.FC<Props> = ({ id }) => {
const { accountState, accountDispatch } = useContext(AccountContext)
const headerHeight = useSafeAreaInsets().top + 44
const footerHeight = useSafeAreaInsets().bottom + useBottomTabBarHeight()
const routes: { key: App.Pages }[] = [
{ key: 'Account_Default' },
{ key: 'Account_All' },
{ key: 'Account_Media' }
]
const renderScene = ({
route
}: {
route: {
key: App.Pages
}
}) => {
return <Timeline page={route.key} account={id} disableRefresh />
}
const renderPager = useCallback(props => <ViewPagerAdapter {...props} />, [])
return (
<TabView
lazy
swipeEnabled
renderPager={renderPager}
renderScene={renderScene}
renderTabBar={() => null}
initialLayout={{ width: Dimensions.get('window').width }}
navigationState={{ index: accountState.segmentedIndex, routes }}
onIndexChange={index =>
accountDispatch({ type: 'segmentedIndex', payload: index })
}
style={[
styles.base,
{
height:
Dimensions.get('window').height -
headerHeight -
footerHeight -
(33 + StyleConstants.Spacing.Global.PagePadding * 2)
}
]}
/>
)
}
const styles = StyleSheet.create({
base: {
marginTop: StyleConstants.Spacing.Global.PagePadding + 33
}
})
export default React.memo(AccountToots, () => true)

View File

@ -1,9 +1,9 @@
import { AccountState } from "./types"
import { AccountState } from './types'
const accountInitialState: AccountState = {
headerRatio: 0.4,
headerRatio: 1 / 3,
informationLayout: { height: 0, y: 100 },
segmentedIndex: 0
}
export default accountInitialState
export default accountInitialState