mirror of
https://github.com/tooot-app/app
synced 2024-12-28 02:10:02 +01:00
Remove most React memo
Maybe would solve iOS out of memory crashes
This commit is contained in:
parent
1e0e8842db
commit
b6045e5121
@ -331,4 +331,4 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default React.memo(Screens, () => true)
|
export default Screens
|
||||||
|
@ -12,55 +12,44 @@ export interface Props {
|
|||||||
potentialWidth?: number
|
potentialWidth?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const InstanceInfo = React.memo(
|
const InstanceInfo: React.FC<Props> = ({ style, header, content, potentialWidth }) => {
|
||||||
({ style, header, content, potentialWidth }: Props) => {
|
const { colors } = useTheme()
|
||||||
const { colors } = useTheme()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
{
|
{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
marginTop: StyleConstants.Spacing.M,
|
marginTop: StyleConstants.Spacing.M,
|
||||||
paddingLeft: StyleConstants.Spacing.Global.PagePadding,
|
paddingLeft: StyleConstants.Spacing.Global.PagePadding,
|
||||||
paddingRight: StyleConstants.Spacing.Global.PagePadding
|
paddingRight: StyleConstants.Spacing.Global.PagePadding
|
||||||
},
|
},
|
||||||
style
|
style
|
||||||
]}
|
]}
|
||||||
accessible
|
accessible
|
||||||
>
|
>
|
||||||
<CustomText
|
<CustomText
|
||||||
fontStyle='S'
|
fontStyle='S'
|
||||||
style={{
|
style={{
|
||||||
marginBottom: StyleConstants.Spacing.XS,
|
marginBottom: StyleConstants.Spacing.XS,
|
||||||
color: colors.primaryDefault
|
color: colors.primaryDefault
|
||||||
}}
|
}}
|
||||||
fontWeight='Bold'
|
fontWeight='Bold'
|
||||||
children={header}
|
children={header}
|
||||||
|
/>
|
||||||
|
{content ? (
|
||||||
|
<CustomText fontStyle='M' style={{ color: colors.primaryDefault }} children={content} />
|
||||||
|
) : (
|
||||||
|
<PlaceholderLine
|
||||||
|
width={potentialWidth ? potentialWidth * StyleConstants.Font.Size.M : undefined}
|
||||||
|
height={StyleConstants.Font.LineHeight.M}
|
||||||
|
color={colors.shimmerDefault}
|
||||||
|
noMargin
|
||||||
|
style={{ borderRadius: 0 }}
|
||||||
/>
|
/>
|
||||||
{content ? (
|
)}
|
||||||
<CustomText
|
</View>
|
||||||
fontStyle='M'
|
)
|
||||||
style={{ color: colors.primaryDefault }}
|
}
|
||||||
children={content}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<PlaceholderLine
|
|
||||||
width={
|
|
||||||
potentialWidth
|
|
||||||
? potentialWidth * StyleConstants.Font.Size.M
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
height={StyleConstants.Font.LineHeight.M}
|
|
||||||
color={colors.shimmerDefault}
|
|
||||||
noMargin
|
|
||||||
style={{ borderRadius: 0 }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
(prev, next) => prev.content === next.content
|
|
||||||
)
|
|
||||||
|
|
||||||
export default InstanceInfo
|
export default InstanceInfo
|
||||||
|
@ -13,74 +13,71 @@ export interface Props {
|
|||||||
queryKey: QueryKeyTimeline
|
queryKey: QueryKeyTimeline
|
||||||
}
|
}
|
||||||
|
|
||||||
const TimelineEmpty = React.memo(
|
const TimelineEmpty: React.FC<Props> = ({ queryKey }) => {
|
||||||
({ queryKey }: Props) => {
|
const { status, refetch } = useTimelineQuery({
|
||||||
const { status, refetch } = useTimelineQuery({
|
...queryKey[1],
|
||||||
...queryKey[1],
|
options: { notifyOnChangeProps: ['status'] }
|
||||||
options: { notifyOnChangeProps: ['status'] }
|
})
|
||||||
})
|
|
||||||
|
|
||||||
const { colors } = useTheme()
|
const { colors } = useTheme()
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
|
|
||||||
const children = () => {
|
const children = () => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 'loading':
|
case 'loading':
|
||||||
return <Circle size={StyleConstants.Font.Size.L} color={colors.secondary} />
|
return <Circle size={StyleConstants.Font.Size.L} color={colors.secondary} />
|
||||||
case 'error':
|
case 'error':
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Icon name='Frown' size={StyleConstants.Font.Size.L} color={colors.primaryDefault} />
|
<Icon name='Frown' size={StyleConstants.Font.Size.L} color={colors.primaryDefault} />
|
||||||
<CustomText
|
<CustomText
|
||||||
fontStyle='M'
|
fontStyle='M'
|
||||||
style={{
|
style={{
|
||||||
marginTop: StyleConstants.Spacing.S,
|
marginTop: StyleConstants.Spacing.S,
|
||||||
marginBottom: StyleConstants.Spacing.L,
|
marginBottom: StyleConstants.Spacing.L,
|
||||||
color: colors.primaryDefault
|
color: colors.primaryDefault
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('empty.error.message')}
|
{t('empty.error.message')}
|
||||||
</CustomText>
|
</CustomText>
|
||||||
<Button type='text' content={t('empty.error.button')} onPress={() => refetch()} />
|
<Button type='text' content={t('empty.error.button')} onPress={() => refetch()} />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
case 'success':
|
case 'success':
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Icon
|
<Icon
|
||||||
name='Smartphone'
|
name='Smartphone'
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
color={colors.primaryDefault}
|
color={colors.primaryDefault}
|
||||||
/>
|
/>
|
||||||
<CustomText
|
<CustomText
|
||||||
fontStyle='M'
|
fontStyle='M'
|
||||||
style={{
|
style={{
|
||||||
marginTop: StyleConstants.Spacing.S,
|
marginTop: StyleConstants.Spacing.S,
|
||||||
marginBottom: StyleConstants.Spacing.L,
|
marginBottom: StyleConstants.Spacing.L,
|
||||||
color: colors.secondary
|
color: colors.secondary
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('empty.success.message')}
|
{t('empty.success.message')}
|
||||||
</CustomText>
|
</CustomText>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return (
|
}
|
||||||
<View
|
return (
|
||||||
style={{
|
<View
|
||||||
flex: 1,
|
style={{
|
||||||
minHeight: '100%',
|
flex: 1,
|
||||||
justifyContent: 'center',
|
minHeight: '100%',
|
||||||
alignItems: 'center',
|
justifyContent: 'center',
|
||||||
backgroundColor: colors.backgroundDefault
|
alignItems: 'center',
|
||||||
}}
|
backgroundColor: colors.backgroundDefault
|
||||||
>
|
}}
|
||||||
{children()}
|
>
|
||||||
</View>
|
{children()}
|
||||||
)
|
</View>
|
||||||
},
|
)
|
||||||
() => true
|
}
|
||||||
)
|
|
||||||
|
|
||||||
export default TimelineEmpty
|
export default TimelineEmpty
|
||||||
|
@ -13,50 +13,47 @@ export interface Props {
|
|||||||
disableInfinity: boolean
|
disableInfinity: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const TimelineFooter = React.memo(
|
const TimelineFooter: React.FC<Props> = ({ queryKey, disableInfinity }) => {
|
||||||
({ queryKey, disableInfinity }: Props) => {
|
const { hasNextPage } = useTimelineQuery({
|
||||||
const { hasNextPage } = useTimelineQuery({
|
...queryKey[1],
|
||||||
...queryKey[1],
|
options: {
|
||||||
options: {
|
enabled: !disableInfinity,
|
||||||
enabled: !disableInfinity,
|
notifyOnChangeProps: ['hasNextPage'],
|
||||||
notifyOnChangeProps: ['hasNextPage'],
|
getNextPageParam: lastPage =>
|
||||||
getNextPageParam: lastPage =>
|
lastPage?.links?.next && {
|
||||||
lastPage?.links?.next && {
|
...(lastPage.links.next.isOffset
|
||||||
...(lastPage.links.next.isOffset
|
? { offset: lastPage.links.next.id }
|
||||||
? { offset: lastPage.links.next.id }
|
: { max_id: lastPage.links.next.id })
|
||||||
: { max_id: lastPage.links.next.id })
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
|
|
||||||
const { colors } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
padding: StyleConstants.Spacing.M
|
padding: StyleConstants.Spacing.M
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{!disableInfinity && hasNextPage ? (
|
{!disableInfinity && hasNextPage ? (
|
||||||
<Circle size={StyleConstants.Font.Size.L} color={colors.secondary} />
|
<Circle size={StyleConstants.Font.Size.L} color={colors.secondary} />
|
||||||
) : (
|
) : (
|
||||||
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
|
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
|
||||||
<Trans
|
<Trans
|
||||||
ns='componentTimeline'
|
ns='componentTimeline'
|
||||||
i18nKey='end.message'
|
i18nKey='end.message'
|
||||||
components={[
|
components={[
|
||||||
<Icon name='Coffee' size={StyleConstants.Font.Size.S} color={colors.secondary} />
|
<Icon name='Coffee' size={StyleConstants.Font.Size.S} color={colors.secondary} />
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</CustomText>
|
</CustomText>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
() => true
|
|
||||||
)
|
|
||||||
|
|
||||||
export default TimelineFooter
|
export default TimelineFooter
|
||||||
|
@ -211,15 +211,14 @@ const TimelineActions: React.FC = () => {
|
|||||||
)
|
)
|
||||||
const childrenReblog = useMemo(() => {
|
const childrenReblog = useMemo(() => {
|
||||||
const color = (state: boolean) => (state ? colors.green : colors.secondary)
|
const color = (state: boolean) => (state ? colors.green : colors.secondary)
|
||||||
|
const disabled =
|
||||||
|
status.visibility === 'direct' || (status.visibility === 'private' && !ownAccount)
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Icon
|
<Icon
|
||||||
name='Repeat'
|
name='Repeat'
|
||||||
color={
|
color={disabled ? colors.disabled : color(status.reblogged)}
|
||||||
status.visibility === 'direct' || (status.visibility === 'private' && !ownAccount)
|
crossOut={disabled}
|
||||||
? colors.disabled
|
|
||||||
: color(status.reblogged)
|
|
||||||
}
|
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
/>
|
/>
|
||||||
{status.reblogs_count > 0 ? (
|
{status.reblogs_count > 0 ? (
|
||||||
|
@ -9,31 +9,28 @@ export interface Props {
|
|||||||
application?: Mastodon.Application
|
application?: Mastodon.Application
|
||||||
}
|
}
|
||||||
|
|
||||||
const HeaderSharedApplication = React.memo(
|
const HeaderSharedApplication: React.FC<Props> = ({ application }) => {
|
||||||
({ application }: Props) => {
|
const { colors } = useTheme()
|
||||||
const { colors } = useTheme()
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { t } = useTranslation('componentTimeline')
|
|
||||||
|
|
||||||
return application && application.name !== 'Web' ? (
|
return application && application.name !== 'Web' ? (
|
||||||
<CustomText
|
<CustomText
|
||||||
fontStyle='S'
|
fontStyle='S'
|
||||||
accessibilityRole='link'
|
accessibilityRole='link'
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
application.website && (await openLink(application.website))
|
application.website && (await openLink(application.website))
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
marginLeft: StyleConstants.Spacing.S,
|
marginLeft: StyleConstants.Spacing.S,
|
||||||
color: colors.secondary
|
color: colors.secondary
|
||||||
}}
|
}}
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
>
|
>
|
||||||
{t('shared.header.shared.application', {
|
{t('shared.header.shared.application', {
|
||||||
application: application.name
|
application: application.name
|
||||||
})}
|
})}
|
||||||
</CustomText>
|
</CustomText>
|
||||||
) : null
|
) : null
|
||||||
},
|
}
|
||||||
() => true
|
|
||||||
)
|
|
||||||
|
|
||||||
export default HeaderSharedApplication
|
export default HeaderSharedApplication
|
||||||
|
@ -13,43 +13,34 @@ export interface Props {
|
|||||||
highlighted?: boolean
|
highlighted?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const HeaderSharedCreated = React.memo(
|
const HeaderSharedCreated: React.FC<Props> = ({ created_at, edited_at, highlighted = false }) => {
|
||||||
({ created_at, edited_at, highlighted = false }: Props) => {
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { colors } = useTheme()
|
||||||
const { colors } = useTheme()
|
|
||||||
|
|
||||||
const actualTime = edited_at || created_at
|
const actualTime = edited_at || created_at
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
|
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
|
||||||
{highlighted ? (
|
{highlighted ? (
|
||||||
<>
|
<>
|
||||||
<FormattedDate
|
<FormattedDate value={new Date(actualTime)} dateStyle='medium' timeStyle='short' />
|
||||||
value={new Date(actualTime)}
|
</>
|
||||||
dateStyle='medium'
|
) : (
|
||||||
timeStyle='short'
|
<RelativeTime time={actualTime} />
|
||||||
/>
|
)}
|
||||||
</>
|
</CustomText>
|
||||||
) : (
|
{edited_at ? (
|
||||||
<RelativeTime time={actualTime} />
|
<Icon
|
||||||
)}
|
accessibilityLabel={t('shared.header.shared.edited.accessibilityLabel')}
|
||||||
</CustomText>
|
name='Edit'
|
||||||
{edited_at ? (
|
size={StyleConstants.Font.Size.S}
|
||||||
<Icon
|
color={colors.secondary}
|
||||||
accessibilityLabel={t(
|
style={{ marginLeft: StyleConstants.Spacing.S }}
|
||||||
'shared.header.shared.edited.accessibilityLabel'
|
/>
|
||||||
)}
|
) : null}
|
||||||
name='Edit'
|
</>
|
||||||
size={StyleConstants.Font.Size.S}
|
)
|
||||||
color={colors.secondary}
|
}
|
||||||
style={{ marginLeft: StyleConstants.Spacing.S }}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
(prev, next) => prev.edited_at === next.edited_at
|
|
||||||
)
|
|
||||||
|
|
||||||
export default HeaderSharedCreated
|
export default HeaderSharedCreated
|
||||||
|
@ -3,34 +3,24 @@ import { StyleConstants } from '@utils/styles/constants'
|
|||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { StyleSheet } from 'react-native'
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
muted?: Mastodon.Status['muted']
|
muted?: Mastodon.Status['muted']
|
||||||
}
|
}
|
||||||
|
|
||||||
const HeaderSharedMuted = React.memo(
|
const HeaderSharedMuted: React.FC<Props> = ({ muted }) => {
|
||||||
({ muted }: Props) => {
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { colors } = useTheme()
|
||||||
const { colors } = useTheme()
|
|
||||||
|
|
||||||
return muted ? (
|
return muted ? (
|
||||||
<Icon
|
<Icon
|
||||||
accessibilityLabel={t('shared.header.shared.muted.accessibilityLabel')}
|
accessibilityLabel={t('shared.header.shared.muted.accessibilityLabel')}
|
||||||
name='VolumeX'
|
name='VolumeX'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.M}
|
||||||
color={colors.secondary}
|
color={colors.secondary}
|
||||||
style={styles.visibility}
|
style={{ marginLeft: StyleConstants.Spacing.S }}
|
||||||
/>
|
/>
|
||||||
) : null
|
) : null
|
||||||
},
|
}
|
||||||
() => true
|
|
||||||
)
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
visibility: {
|
|
||||||
marginLeft: StyleConstants.Spacing.S
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
export default HeaderSharedMuted
|
export default HeaderSharedMuted
|
||||||
|
@ -9,48 +9,45 @@ export interface Props {
|
|||||||
visibility: Mastodon.Status['visibility']
|
visibility: Mastodon.Status['visibility']
|
||||||
}
|
}
|
||||||
|
|
||||||
const HeaderSharedVisibility = React.memo(
|
const HeaderSharedVisibility: React.FC<Props> = ({ visibility }) => {
|
||||||
({ visibility }: Props) => {
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { colors } = useTheme()
|
||||||
const { colors } = useTheme()
|
|
||||||
|
|
||||||
switch (visibility) {
|
switch (visibility) {
|
||||||
case 'unlisted':
|
case 'unlisted':
|
||||||
return (
|
return (
|
||||||
<Icon
|
<Icon
|
||||||
accessibilityLabel={t('shared.header.shared.visibility.private.accessibilityLabel')}
|
accessibilityLabel={t('shared.header.shared.visibility.private.accessibilityLabel')}
|
||||||
name='Unlock'
|
name='Unlock'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={colors.secondary}
|
color={colors.secondary}
|
||||||
style={styles.visibility}
|
style={styles.visibility}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
case 'private':
|
case 'private':
|
||||||
return (
|
return (
|
||||||
<Icon
|
<Icon
|
||||||
accessibilityLabel={t('shared.header.shared.visibility.private.accessibilityLabel')}
|
accessibilityLabel={t('shared.header.shared.visibility.private.accessibilityLabel')}
|
||||||
name='Lock'
|
name='Lock'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={colors.secondary}
|
color={colors.secondary}
|
||||||
style={styles.visibility}
|
style={styles.visibility}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
case 'direct':
|
case 'direct':
|
||||||
return (
|
return (
|
||||||
<Icon
|
<Icon
|
||||||
accessibilityLabel={t('shared.header.shared.visibility.direct.accessibilityLabel')}
|
accessibilityLabel={t('shared.header.shared.visibility.direct.accessibilityLabel')}
|
||||||
name='Mail'
|
name='Mail'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={colors.secondary}
|
color={colors.secondary}
|
||||||
style={styles.visibility}
|
style={styles.visibility}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
() => true
|
|
||||||
)
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
visibility: {
|
visibility: {
|
||||||
|
@ -3,25 +3,18 @@ import { Modal, View } from 'react-native'
|
|||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import ComposeContext from './utils/createContext'
|
import ComposeContext from './utils/createContext'
|
||||||
|
|
||||||
const ComposePosting = React.memo(
|
const ComposePosting = () => {
|
||||||
() => {
|
const { composeState } = useContext(ComposeContext)
|
||||||
const { composeState } = useContext(ComposeContext)
|
const { colors } = useTheme()
|
||||||
const { colors } = useTheme()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
transparent
|
transparent
|
||||||
animationType='fade'
|
animationType='fade'
|
||||||
visible={composeState.posting}
|
visible={composeState.posting}
|
||||||
children={
|
children={<View style={{ flex: 1, backgroundColor: colors.backgroundOverlayInvert }} />}
|
||||||
<View
|
/>
|
||||||
style={{ flex: 1, backgroundColor: colors.backgroundOverlayInvert }}
|
)
|
||||||
/>
|
}
|
||||||
}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
() => true
|
|
||||||
)
|
|
||||||
|
|
||||||
export default ComposePosting
|
export default ComposePosting
|
||||||
|
@ -17,87 +17,84 @@ import { getInstanceConfigurationStatusCharsURL } from '@utils/slices/instancesS
|
|||||||
|
|
||||||
export let instanceConfigurationStatusCharsURL = 23
|
export let instanceConfigurationStatusCharsURL = 23
|
||||||
|
|
||||||
const ComposeRoot = React.memo(
|
const ComposeRoot = () => {
|
||||||
() => {
|
const { colors } = useTheme()
|
||||||
const { colors } = useTheme()
|
|
||||||
|
|
||||||
instanceConfigurationStatusCharsURL = useSelector(
|
instanceConfigurationStatusCharsURL = useSelector(
|
||||||
getInstanceConfigurationStatusCharsURL,
|
getInstanceConfigurationStatusCharsURL,
|
||||||
() => true
|
() => true
|
||||||
)
|
)
|
||||||
|
|
||||||
const accessibleRefDrafts = useRef(null)
|
const accessibleRefDrafts = useRef(null)
|
||||||
const accessibleRefAttachments = useRef(null)
|
const accessibleRefAttachments = useRef(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const tagDrafts = findNodeHandle(accessibleRefDrafts.current)
|
const tagDrafts = findNodeHandle(accessibleRefDrafts.current)
|
||||||
tagDrafts && AccessibilityInfo.setAccessibilityFocus(tagDrafts)
|
tagDrafts && AccessibilityInfo.setAccessibilityFocus(tagDrafts)
|
||||||
}, [accessibleRefDrafts.current])
|
}, [accessibleRefDrafts.current])
|
||||||
|
|
||||||
const { composeState } = useContext(ComposeContext)
|
const { composeState } = useContext(ComposeContext)
|
||||||
|
|
||||||
const mapSchemaToType = () => {
|
const mapSchemaToType = () => {
|
||||||
if (composeState.tag) {
|
if (composeState.tag) {
|
||||||
switch (composeState.tag?.schema) {
|
switch (composeState.tag?.schema) {
|
||||||
case '@':
|
case '@':
|
||||||
return 'accounts'
|
return 'accounts'
|
||||||
case '#':
|
case '#':
|
||||||
return 'hashtags'
|
return 'hashtags'
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return undefined
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return undefined
|
||||||
}
|
}
|
||||||
const { isFetching, data, refetch } = useSearchQuery({
|
}
|
||||||
type: mapSchemaToType(),
|
const { isFetching, data, refetch } = useSearchQuery({
|
||||||
term: composeState.tag?.raw.substring(1),
|
type: mapSchemaToType(),
|
||||||
options: { enabled: false }
|
term: composeState.tag?.raw.substring(1),
|
||||||
})
|
options: { enabled: false }
|
||||||
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
(composeState.tag?.schema === '@' || composeState.tag?.schema === '#') &&
|
(composeState.tag?.schema === '@' || composeState.tag?.schema === '#') &&
|
||||||
composeState.tag?.raw
|
composeState.tag?.raw
|
||||||
) {
|
) {
|
||||||
refetch()
|
refetch()
|
||||||
}
|
}
|
||||||
}, [composeState.tag])
|
}, [composeState.tag])
|
||||||
|
|
||||||
const listEmpty = useMemo(() => {
|
const listEmpty = useMemo(() => {
|
||||||
if (isFetching) {
|
if (isFetching) {
|
||||||
return (
|
return (
|
||||||
<View key='listEmpty' style={{ flex: 1, alignItems: 'center' }}>
|
<View key='listEmpty' style={{ flex: 1, alignItems: 'center' }}>
|
||||||
<Circle size={StyleConstants.Font.Size.M * 1.25} color={colors.secondary} />
|
<Circle size={StyleConstants.Font.Size.M * 1.25} color={colors.secondary} />
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}, [isFetching])
|
}, [isFetching])
|
||||||
|
|
||||||
const Footer = useMemo(
|
const Footer = useMemo(
|
||||||
() => <ComposeRootFooter accessibleRefAttachments={accessibleRefAttachments} />,
|
() => <ComposeRootFooter accessibleRefAttachments={accessibleRefAttachments} />,
|
||||||
[accessibleRefAttachments.current]
|
[accessibleRefAttachments.current]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{ flex: 1 }}>
|
<View style={{ flex: 1 }}>
|
||||||
<FlatList
|
<FlatList
|
||||||
renderItem={({ item }) => <ComposeRootSuggestion item={item} />}
|
renderItem={({ item }) => <ComposeRootSuggestion item={item} />}
|
||||||
ListEmptyComponent={listEmpty}
|
ListEmptyComponent={listEmpty}
|
||||||
keyboardShouldPersistTaps='always'
|
keyboardShouldPersistTaps='always'
|
||||||
ListHeaderComponent={ComposeRootHeader}
|
ListHeaderComponent={ComposeRootHeader}
|
||||||
ListFooterComponent={Footer}
|
ListFooterComponent={Footer}
|
||||||
ItemSeparatorComponent={ComponentSeparator}
|
ItemSeparatorComponent={ComponentSeparator}
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
data={data ? data[mapSchemaToType()] : undefined}
|
data={data ? data[mapSchemaToType()] : undefined}
|
||||||
keyExtractor={() => Math.random().toString()}
|
keyExtractor={() => Math.random().toString()}
|
||||||
/>
|
/>
|
||||||
<ComposeActions />
|
<ComposeActions />
|
||||||
<ComposeDrafts accessibleRefDrafts={accessibleRefDrafts} />
|
<ComposeDrafts accessibleRefDrafts={accessibleRefDrafts} />
|
||||||
<ComposePosting />
|
<ComposePosting />
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
() => true
|
|
||||||
)
|
|
||||||
|
|
||||||
export default ComposeRoot
|
export default ComposeRoot
|
||||||
|
@ -292,4 +292,4 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default React.memo(ComposeAttachments, () => true)
|
export default ComposeAttachments
|
||||||
|
@ -31,4 +31,4 @@ const ComposeReply: React.FC = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default React.memo(ComposeReply, () => true)
|
export default ComposeReply
|
||||||
|
@ -1,34 +1,25 @@
|
|||||||
import CustomText from '@components/Text'
|
import CustomText from '@components/Text'
|
||||||
import {
|
import { getInstanceAccount, getInstanceUri } from '@utils/slices/instancesSlice'
|
||||||
getInstanceAccount,
|
|
||||||
getInstanceUri
|
|
||||||
} from '@utils/slices/instancesSlice'
|
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
|
|
||||||
const ComposePostingAs = React.memo(
|
const ComposePostingAs = () => {
|
||||||
() => {
|
const { t } = useTranslation('screenCompose')
|
||||||
const { t } = useTranslation('screenCompose')
|
const { colors } = useTheme()
|
||||||
const { colors } = useTheme()
|
|
||||||
|
|
||||||
const instanceAccount = useSelector(
|
const instanceAccount = useSelector(getInstanceAccount, (prev, next) => prev?.acct === next?.acct)
|
||||||
getInstanceAccount,
|
const instanceUri = useSelector(getInstanceUri)
|
||||||
(prev, next) => prev?.acct === next?.acct
|
|
||||||
)
|
|
||||||
const instanceUri = useSelector(getInstanceUri)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
|
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
|
||||||
{t('content.root.header.postingAs', {
|
{t('content.root.header.postingAs', {
|
||||||
acct: instanceAccount?.acct,
|
acct: instanceAccount?.acct,
|
||||||
domain: instanceUri
|
domain: instanceUri
|
||||||
})}
|
})}
|
||||||
</CustomText>
|
</CustomText>
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
() => true
|
|
||||||
)
|
|
||||||
|
|
||||||
export default ComposePostingAs
|
export default ComposePostingAs
|
||||||
|
@ -16,103 +16,100 @@ import TabPublic from './Tabs/Public'
|
|||||||
|
|
||||||
const Tab = createBottomTabNavigator<ScreenTabsStackParamList>()
|
const Tab = createBottomTabNavigator<ScreenTabsStackParamList>()
|
||||||
|
|
||||||
const ScreenTabs = React.memo(
|
const ScreenTabs = ({ navigation }: RootStackScreenProps<'Screen-Tabs'>) => {
|
||||||
({ navigation }: RootStackScreenProps<'Screen-Tabs'>) => {
|
const { colors } = useTheme()
|
||||||
const { colors } = useTheme()
|
|
||||||
|
|
||||||
const instanceActive = useSelector(getInstanceActive)
|
const instanceActive = useSelector(getInstanceActive)
|
||||||
const instanceAccount = useSelector(
|
const instanceAccount = useSelector(
|
||||||
getInstanceAccount,
|
getInstanceAccount,
|
||||||
(prev, next) => prev?.avatarStatic === next?.avatarStatic
|
(prev, next) => prev?.avatarStatic === next?.avatarStatic
|
||||||
)
|
)
|
||||||
|
|
||||||
const composeListeners = useMemo(
|
const composeListeners = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
tabPress: (e: any) => {
|
tabPress: (e: any) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
haptics('Light')
|
haptics('Light')
|
||||||
navigation.navigate('Screen-Compose')
|
navigation.navigate('Screen-Compose')
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
const composeComponent = useCallback(() => null, [])
|
const composeComponent = useCallback(() => null, [])
|
||||||
|
|
||||||
const meListeners = useMemo(
|
const meListeners = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
tabLongPress: () => {
|
tabLongPress: () => {
|
||||||
haptics('Light')
|
haptics('Light')
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
navigation.navigate('Tab-Me', { screen: 'Tab-Me-Root' })
|
navigation.navigate('Tab-Me', { screen: 'Tab-Me-Root' })
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
navigation.navigate('Tab-Me', { screen: 'Tab-Me-Switch' })
|
navigation.navigate('Tab-Me', { screen: 'Tab-Me-Switch' })
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
|
|
||||||
const previousTab = useSelector(getPreviousTab, () => true)
|
const previousTab = useSelector(getPreviousTab, () => true)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tab.Navigator
|
<Tab.Navigator
|
||||||
initialRouteName={instanceActive !== -1 ? previousTab : 'Tab-Me'}
|
initialRouteName={instanceActive !== -1 ? previousTab : 'Tab-Me'}
|
||||||
screenOptions={({ route }) => ({
|
screenOptions={({ route }) => ({
|
||||||
headerShown: false,
|
headerShown: false,
|
||||||
tabBarActiveTintColor: colors.primaryDefault,
|
tabBarActiveTintColor: colors.primaryDefault,
|
||||||
tabBarInactiveTintColor: colors.secondary,
|
tabBarInactiveTintColor: colors.secondary,
|
||||||
tabBarShowLabel: false,
|
tabBarShowLabel: false,
|
||||||
...(Platform.OS === 'android' && { tabBarHideOnKeyboard: true }),
|
...(Platform.OS === 'android' && { tabBarHideOnKeyboard: true }),
|
||||||
tabBarStyle: { display: instanceActive !== -1 ? 'flex' : 'none' },
|
tabBarStyle: { display: instanceActive !== -1 ? 'flex' : 'none' },
|
||||||
tabBarIcon: ({
|
tabBarIcon: ({
|
||||||
focused,
|
focused,
|
||||||
color,
|
color,
|
||||||
size
|
size
|
||||||
}: {
|
}: {
|
||||||
focused: boolean
|
focused: boolean
|
||||||
color: string
|
color: string
|
||||||
size: number
|
size: number
|
||||||
}) => {
|
}) => {
|
||||||
switch (route.name) {
|
switch (route.name) {
|
||||||
case 'Tab-Local':
|
case 'Tab-Local':
|
||||||
return <Icon name='Home' size={size} color={color} />
|
return <Icon name='Home' size={size} color={color} />
|
||||||
case 'Tab-Public':
|
case 'Tab-Public':
|
||||||
return <Icon name='Globe' size={size} color={color} />
|
return <Icon name='Globe' size={size} color={color} />
|
||||||
case 'Tab-Compose':
|
case 'Tab-Compose':
|
||||||
return <Icon name='Plus' size={size} color={color} />
|
return <Icon name='Plus' size={size} color={color} />
|
||||||
case 'Tab-Notifications':
|
case 'Tab-Notifications':
|
||||||
return <Icon name='Bell' size={size} color={color} />
|
return <Icon name='Bell' size={size} color={color} />
|
||||||
case 'Tab-Me':
|
case 'Tab-Me':
|
||||||
return (
|
return (
|
||||||
<GracefullyImage
|
<GracefullyImage
|
||||||
key={instanceAccount?.avatarStatic}
|
key={instanceAccount?.avatarStatic}
|
||||||
uri={{ original: instanceAccount?.avatarStatic }}
|
uri={{ original: instanceAccount?.avatarStatic }}
|
||||||
dimension={{
|
dimension={{
|
||||||
width: size,
|
width: size,
|
||||||
height: size
|
height: size
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
borderRadius: size,
|
borderRadius: size,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
borderWidth: focused ? 2 : 0,
|
borderWidth: focused ? 2 : 0,
|
||||||
borderColor: focused ? colors.secondary : color
|
borderColor: focused ? colors.secondary : color
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
default:
|
default:
|
||||||
return <Icon name='AlertOctagon' size={size} color={color} />
|
return <Icon name='AlertOctagon' size={size} color={color} />
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})}
|
}
|
||||||
>
|
})}
|
||||||
<Tab.Screen name='Tab-Local' component={TabLocal} />
|
>
|
||||||
<Tab.Screen name='Tab-Public' component={TabPublic} />
|
<Tab.Screen name='Tab-Local' component={TabLocal} />
|
||||||
<Tab.Screen name='Tab-Compose' component={composeComponent} listeners={composeListeners} />
|
<Tab.Screen name='Tab-Public' component={TabPublic} />
|
||||||
<Tab.Screen name='Tab-Notifications' component={TabNotifications} />
|
<Tab.Screen name='Tab-Compose' component={composeComponent} listeners={composeListeners} />
|
||||||
<Tab.Screen name='Tab-Me' component={TabMe} listeners={meListeners} />
|
<Tab.Screen name='Tab-Notifications' component={TabNotifications} />
|
||||||
</Tab.Navigator>
|
<Tab.Screen name='Tab-Me' component={TabMe} listeners={meListeners} />
|
||||||
)
|
</Tab.Navigator>
|
||||||
},
|
)
|
||||||
() => true
|
}
|
||||||
)
|
|
||||||
|
|
||||||
export default ScreenTabs
|
export default ScreenTabs
|
||||||
|
@ -3,22 +3,17 @@ import TimelineDefault from '@components/Timeline/Default'
|
|||||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
const TabMeBookmarks = React.memo(
|
const TabMeBookmarks = () => {
|
||||||
() => {
|
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Bookmarks' }]
|
||||||
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Bookmarks' }]
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Timeline
|
<Timeline
|
||||||
queryKey={queryKey}
|
queryKey={queryKey}
|
||||||
customProps={{
|
customProps={{
|
||||||
renderItem: ({ item }) => (
|
renderItem: ({ item }) => <TimelineDefault item={item} queryKey={queryKey} />
|
||||||
<TimelineDefault item={item} queryKey={queryKey} />
|
}}
|
||||||
)
|
/>
|
||||||
}}
|
)
|
||||||
/>
|
}
|
||||||
)
|
|
||||||
},
|
|
||||||
() => true
|
|
||||||
)
|
|
||||||
|
|
||||||
export default TabMeBookmarks
|
export default TabMeBookmarks
|
||||||
|
@ -3,22 +3,17 @@ import TimelineConversation from '@components/Timeline/Conversation'
|
|||||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
const TabMeConversations = React.memo(
|
const TabMeConversations = () => {
|
||||||
() => {
|
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Conversations' }]
|
||||||
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Conversations' }]
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Timeline
|
<Timeline
|
||||||
queryKey={queryKey}
|
queryKey={queryKey}
|
||||||
customProps={{
|
customProps={{
|
||||||
renderItem: ({ item }) => (
|
renderItem: ({ item }) => <TimelineConversation conversation={item} queryKey={queryKey} />
|
||||||
<TimelineConversation conversation={item} queryKey={queryKey} />
|
}}
|
||||||
)
|
/>
|
||||||
}}
|
)
|
||||||
/>
|
}
|
||||||
)
|
|
||||||
},
|
|
||||||
() => true
|
|
||||||
)
|
|
||||||
|
|
||||||
export default TabMeConversations
|
export default TabMeConversations
|
||||||
|
@ -3,22 +3,17 @@ import TimelineDefault from '@components/Timeline/Default'
|
|||||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
const TabMeFavourites = React.memo(
|
const TabMeFavourites = () => {
|
||||||
() => {
|
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Favourites' }]
|
||||||
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Favourites' }]
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Timeline
|
<Timeline
|
||||||
queryKey={queryKey}
|
queryKey={queryKey}
|
||||||
customProps={{
|
customProps={{
|
||||||
renderItem: ({ item }) => (
|
renderItem: ({ item }) => <TimelineDefault item={item} queryKey={queryKey} />
|
||||||
<TimelineDefault item={item} queryKey={queryKey} />
|
}}
|
||||||
)
|
/>
|
||||||
}}
|
)
|
||||||
/>
|
}
|
||||||
)
|
|
||||||
},
|
|
||||||
() => true
|
|
||||||
)
|
|
||||||
|
|
||||||
export default TabMeFavourites
|
export default TabMeFavourites
|
||||||
|
@ -12,65 +12,62 @@ export interface Props {
|
|||||||
account: Mastodon.Account | undefined
|
account: Mastodon.Account | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
const AccountNav = React.memo(
|
const AccountNav: React.FC<Props> = ({ scrollY, account }) => {
|
||||||
({ scrollY, account }: Props) => {
|
const { colors } = useTheme()
|
||||||
const { colors } = useTheme()
|
const headerHeight = useSafeAreaInsets().top + 44
|
||||||
const headerHeight = useSafeAreaInsets().top + 44
|
|
||||||
|
|
||||||
const nameY =
|
const nameY =
|
||||||
Dimensions.get('window').width / 3 +
|
Dimensions.get('window').width / 3 +
|
||||||
StyleConstants.Avatar.L -
|
StyleConstants.Avatar.L -
|
||||||
StyleConstants.Spacing.Global.PagePadding * 2 +
|
StyleConstants.Spacing.Global.PagePadding * 2 +
|
||||||
StyleConstants.Spacing.M -
|
StyleConstants.Spacing.M -
|
||||||
headerHeight
|
headerHeight
|
||||||
|
|
||||||
const styleOpacity = useAnimatedStyle(() => {
|
const styleOpacity = useAnimatedStyle(() => {
|
||||||
return {
|
return {
|
||||||
opacity: interpolate(scrollY.value, [0, 200], [0, 1], Extrapolate.CLAMP)
|
opacity: interpolate(scrollY.value, [0, 200], [0, 1], Extrapolate.CLAMP)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const styleMarginTop = useAnimatedStyle(() => {
|
const styleMarginTop = useAnimatedStyle(() => {
|
||||||
return {
|
return {
|
||||||
marginTop: interpolate(scrollY.value, [nameY, nameY + 20], [50, 0], Extrapolate.CLAMP)
|
marginTop: interpolate(scrollY.value, [nameY, nameY + 20], [50, 0], Extrapolate.CLAMP)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Animated.View
|
<Animated.View
|
||||||
style={[
|
style={[
|
||||||
styleOpacity,
|
styleOpacity,
|
||||||
{
|
{
|
||||||
...StyleSheet.absoluteFillObject,
|
...StyleSheet.absoluteFillObject,
|
||||||
zIndex: 99,
|
zIndex: 99,
|
||||||
backgroundColor: colors.backgroundDefault,
|
backgroundColor: colors.backgroundDefault,
|
||||||
height: headerHeight
|
height: headerHeight
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
overflow: 'hidden',
|
||||||
|
marginTop: useSafeAreaInsets().top + (44 - StyleConstants.Font.Size.L) / 2
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<View
|
<Animated.View style={[{ flexDirection: 'row' }, styleMarginTop]}>
|
||||||
style={{
|
{account ? (
|
||||||
flex: 1,
|
<CustomText numberOfLines={1}>
|
||||||
alignItems: 'center',
|
<ParseEmojis
|
||||||
overflow: 'hidden',
|
content={account.display_name || account.username}
|
||||||
marginTop: useSafeAreaInsets().top + (44 - StyleConstants.Font.Size.L) / 2
|
emojis={account.emojis}
|
||||||
}}
|
fontBold
|
||||||
>
|
/>
|
||||||
<Animated.View style={[{ flexDirection: 'row' }, styleMarginTop]}>
|
</CustomText>
|
||||||
{account ? (
|
) : null}
|
||||||
<CustomText numberOfLines={1}>
|
</Animated.View>
|
||||||
<ParseEmojis
|
</View>
|
||||||
content={account.display_name || account.username}
|
</Animated.View>
|
||||||
emojis={account.emojis}
|
)
|
||||||
fontBold
|
}
|
||||||
/>
|
|
||||||
</CustomText>
|
|
||||||
) : null}
|
|
||||||
</Animated.View>
|
|
||||||
</View>
|
|
||||||
</Animated.View>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
(_, next) => next.account === undefined
|
|
||||||
)
|
|
||||||
|
|
||||||
export default AccountNav
|
export default AccountNav
|
||||||
|
Loading…
Reference in New Issue
Block a user