1
0
mirror of https://github.com/tooot-app/app synced 2025-06-05 22:19:13 +02:00

Remove most React memo

Maybe would solve iOS out of memory crashes
This commit is contained in:
xmflsct
2022-12-24 01:18:20 +01:00
parent 1e0e8842db
commit b6045e5121
19 changed files with 517 additions and 600 deletions

View File

@@ -3,25 +3,18 @@ import { Modal, View } from 'react-native'
import { useTheme } from '@utils/styles/ThemeManager'
import ComposeContext from './utils/createContext'
const ComposePosting = React.memo(
() => {
const { composeState } = useContext(ComposeContext)
const { colors } = useTheme()
const ComposePosting = () => {
const { composeState } = useContext(ComposeContext)
const { colors } = useTheme()
return (
<Modal
transparent
animationType='fade'
visible={composeState.posting}
children={
<View
style={{ flex: 1, backgroundColor: colors.backgroundOverlayInvert }}
/>
}
/>
)
},
() => true
)
return (
<Modal
transparent
animationType='fade'
visible={composeState.posting}
children={<View style={{ flex: 1, backgroundColor: colors.backgroundOverlayInvert }} />}
/>
)
}
export default ComposePosting

View File

@@ -17,87 +17,84 @@ import { getInstanceConfigurationStatusCharsURL } from '@utils/slices/instancesS
export let instanceConfigurationStatusCharsURL = 23
const ComposeRoot = React.memo(
() => {
const { colors } = useTheme()
const ComposeRoot = () => {
const { colors } = useTheme()
instanceConfigurationStatusCharsURL = useSelector(
getInstanceConfigurationStatusCharsURL,
() => true
)
instanceConfigurationStatusCharsURL = useSelector(
getInstanceConfigurationStatusCharsURL,
() => true
)
const accessibleRefDrafts = useRef(null)
const accessibleRefAttachments = useRef(null)
const accessibleRefDrafts = useRef(null)
const accessibleRefAttachments = useRef(null)
useEffect(() => {
const tagDrafts = findNodeHandle(accessibleRefDrafts.current)
tagDrafts && AccessibilityInfo.setAccessibilityFocus(tagDrafts)
}, [accessibleRefDrafts.current])
useEffect(() => {
const tagDrafts = findNodeHandle(accessibleRefDrafts.current)
tagDrafts && AccessibilityInfo.setAccessibilityFocus(tagDrafts)
}, [accessibleRefDrafts.current])
const { composeState } = useContext(ComposeContext)
const { composeState } = useContext(ComposeContext)
const mapSchemaToType = () => {
if (composeState.tag) {
switch (composeState.tag?.schema) {
case '@':
return 'accounts'
case '#':
return 'hashtags'
}
} else {
return undefined
const mapSchemaToType = () => {
if (composeState.tag) {
switch (composeState.tag?.schema) {
case '@':
return 'accounts'
case '#':
return 'hashtags'
}
} else {
return undefined
}
const { isFetching, data, refetch } = useSearchQuery({
type: mapSchemaToType(),
term: composeState.tag?.raw.substring(1),
options: { enabled: false }
})
}
const { isFetching, data, refetch } = useSearchQuery({
type: mapSchemaToType(),
term: composeState.tag?.raw.substring(1),
options: { enabled: false }
})
useEffect(() => {
if (
(composeState.tag?.schema === '@' || composeState.tag?.schema === '#') &&
composeState.tag?.raw
) {
refetch()
}
}, [composeState.tag])
useEffect(() => {
if (
(composeState.tag?.schema === '@' || composeState.tag?.schema === '#') &&
composeState.tag?.raw
) {
refetch()
}
}, [composeState.tag])
const listEmpty = useMemo(() => {
if (isFetching) {
return (
<View key='listEmpty' style={{ flex: 1, alignItems: 'center' }}>
<Circle size={StyleConstants.Font.Size.M * 1.25} color={colors.secondary} />
</View>
)
}
}, [isFetching])
const listEmpty = useMemo(() => {
if (isFetching) {
return (
<View key='listEmpty' style={{ flex: 1, alignItems: 'center' }}>
<Circle size={StyleConstants.Font.Size.M * 1.25} color={colors.secondary} />
</View>
)
}
}, [isFetching])
const Footer = useMemo(
() => <ComposeRootFooter accessibleRefAttachments={accessibleRefAttachments} />,
[accessibleRefAttachments.current]
)
const Footer = useMemo(
() => <ComposeRootFooter accessibleRefAttachments={accessibleRefAttachments} />,
[accessibleRefAttachments.current]
)
return (
<View style={{ flex: 1 }}>
<FlatList
renderItem={({ item }) => <ComposeRootSuggestion item={item} />}
ListEmptyComponent={listEmpty}
keyboardShouldPersistTaps='always'
ListHeaderComponent={ComposeRootHeader}
ListFooterComponent={Footer}
ItemSeparatorComponent={ComponentSeparator}
// @ts-ignore
data={data ? data[mapSchemaToType()] : undefined}
keyExtractor={() => Math.random().toString()}
/>
<ComposeActions />
<ComposeDrafts accessibleRefDrafts={accessibleRefDrafts} />
<ComposePosting />
</View>
)
},
() => true
)
return (
<View style={{ flex: 1 }}>
<FlatList
renderItem={({ item }) => <ComposeRootSuggestion item={item} />}
ListEmptyComponent={listEmpty}
keyboardShouldPersistTaps='always'
ListHeaderComponent={ComposeRootHeader}
ListFooterComponent={Footer}
ItemSeparatorComponent={ComponentSeparator}
// @ts-ignore
data={data ? data[mapSchemaToType()] : undefined}
keyExtractor={() => Math.random().toString()}
/>
<ComposeActions />
<ComposeDrafts accessibleRefDrafts={accessibleRefDrafts} />
<ComposePosting />
</View>
)
}
export default ComposeRoot

View File

@@ -292,4 +292,4 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
)
}
export default React.memo(ComposeAttachments, () => true)
export default ComposeAttachments

View File

@@ -31,4 +31,4 @@ const ComposeReply: React.FC = () => {
)
}
export default React.memo(ComposeReply, () => true)
export default ComposeReply

View File

@@ -1,34 +1,25 @@
import CustomText from '@components/Text'
import {
getInstanceAccount,
getInstanceUri
} from '@utils/slices/instancesSlice'
import { getInstanceAccount, getInstanceUri } from '@utils/slices/instancesSlice'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { useSelector } from 'react-redux'
const ComposePostingAs = React.memo(
() => {
const { t } = useTranslation('screenCompose')
const { colors } = useTheme()
const ComposePostingAs = () => {
const { t } = useTranslation('screenCompose')
const { colors } = useTheme()
const instanceAccount = useSelector(
getInstanceAccount,
(prev, next) => prev?.acct === next?.acct
)
const instanceUri = useSelector(getInstanceUri)
const instanceAccount = useSelector(getInstanceAccount, (prev, next) => prev?.acct === next?.acct)
const instanceUri = useSelector(getInstanceUri)
return (
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
{t('content.root.header.postingAs', {
acct: instanceAccount?.acct,
domain: instanceUri
})}
</CustomText>
)
},
() => true
)
return (
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
{t('content.root.header.postingAs', {
acct: instanceAccount?.acct,
domain: instanceUri
})}
</CustomText>
)
}
export default ComposePostingAs

View File

@@ -16,103 +16,100 @@ import TabPublic from './Tabs/Public'
const Tab = createBottomTabNavigator<ScreenTabsStackParamList>()
const ScreenTabs = React.memo(
({ navigation }: RootStackScreenProps<'Screen-Tabs'>) => {
const { colors } = useTheme()
const ScreenTabs = ({ navigation }: RootStackScreenProps<'Screen-Tabs'>) => {
const { colors } = useTheme()
const instanceActive = useSelector(getInstanceActive)
const instanceAccount = useSelector(
getInstanceAccount,
(prev, next) => prev?.avatarStatic === next?.avatarStatic
)
const instanceActive = useSelector(getInstanceActive)
const instanceAccount = useSelector(
getInstanceAccount,
(prev, next) => prev?.avatarStatic === next?.avatarStatic
)
const composeListeners = useMemo(
() => ({
tabPress: (e: any) => {
e.preventDefault()
haptics('Light')
navigation.navigate('Screen-Compose')
}
}),
[]
)
const composeComponent = useCallback(() => null, [])
const composeListeners = useMemo(
() => ({
tabPress: (e: any) => {
e.preventDefault()
haptics('Light')
navigation.navigate('Screen-Compose')
}
}),
[]
)
const composeComponent = useCallback(() => null, [])
const meListeners = useMemo(
() => ({
tabLongPress: () => {
haptics('Light')
//@ts-ignore
navigation.navigate('Tab-Me', { screen: 'Tab-Me-Root' })
//@ts-ignore
navigation.navigate('Tab-Me', { screen: 'Tab-Me-Switch' })
}
}),
[]
)
const meListeners = useMemo(
() => ({
tabLongPress: () => {
haptics('Light')
//@ts-ignore
navigation.navigate('Tab-Me', { screen: 'Tab-Me-Root' })
//@ts-ignore
navigation.navigate('Tab-Me', { screen: 'Tab-Me-Switch' })
}
}),
[]
)
const previousTab = useSelector(getPreviousTab, () => true)
const previousTab = useSelector(getPreviousTab, () => true)
return (
<Tab.Navigator
initialRouteName={instanceActive !== -1 ? previousTab : 'Tab-Me'}
screenOptions={({ route }) => ({
headerShown: false,
tabBarActiveTintColor: colors.primaryDefault,
tabBarInactiveTintColor: colors.secondary,
tabBarShowLabel: false,
...(Platform.OS === 'android' && { tabBarHideOnKeyboard: true }),
tabBarStyle: { display: instanceActive !== -1 ? 'flex' : 'none' },
tabBarIcon: ({
focused,
color,
size
}: {
focused: boolean
color: string
size: number
}) => {
switch (route.name) {
case 'Tab-Local':
return <Icon name='Home' size={size} color={color} />
case 'Tab-Public':
return <Icon name='Globe' size={size} color={color} />
case 'Tab-Compose':
return <Icon name='Plus' size={size} color={color} />
case 'Tab-Notifications':
return <Icon name='Bell' size={size} color={color} />
case 'Tab-Me':
return (
<GracefullyImage
key={instanceAccount?.avatarStatic}
uri={{ original: instanceAccount?.avatarStatic }}
dimension={{
width: size,
height: size
}}
style={{
borderRadius: size,
overflow: 'hidden',
borderWidth: focused ? 2 : 0,
borderColor: focused ? colors.secondary : color
}}
/>
)
default:
return <Icon name='AlertOctagon' size={size} color={color} />
}
return (
<Tab.Navigator
initialRouteName={instanceActive !== -1 ? previousTab : 'Tab-Me'}
screenOptions={({ route }) => ({
headerShown: false,
tabBarActiveTintColor: colors.primaryDefault,
tabBarInactiveTintColor: colors.secondary,
tabBarShowLabel: false,
...(Platform.OS === 'android' && { tabBarHideOnKeyboard: true }),
tabBarStyle: { display: instanceActive !== -1 ? 'flex' : 'none' },
tabBarIcon: ({
focused,
color,
size
}: {
focused: boolean
color: string
size: number
}) => {
switch (route.name) {
case 'Tab-Local':
return <Icon name='Home' size={size} color={color} />
case 'Tab-Public':
return <Icon name='Globe' size={size} color={color} />
case 'Tab-Compose':
return <Icon name='Plus' size={size} color={color} />
case 'Tab-Notifications':
return <Icon name='Bell' size={size} color={color} />
case 'Tab-Me':
return (
<GracefullyImage
key={instanceAccount?.avatarStatic}
uri={{ original: instanceAccount?.avatarStatic }}
dimension={{
width: size,
height: size
}}
style={{
borderRadius: size,
overflow: 'hidden',
borderWidth: focused ? 2 : 0,
borderColor: focused ? colors.secondary : color
}}
/>
)
default:
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-Compose' component={composeComponent} listeners={composeListeners} />
<Tab.Screen name='Tab-Notifications' component={TabNotifications} />
<Tab.Screen name='Tab-Me' component={TabMe} listeners={meListeners} />
</Tab.Navigator>
)
},
() => true
)
}
})}
>
<Tab.Screen name='Tab-Local' component={TabLocal} />
<Tab.Screen name='Tab-Public' component={TabPublic} />
<Tab.Screen name='Tab-Compose' component={composeComponent} listeners={composeListeners} />
<Tab.Screen name='Tab-Notifications' component={TabNotifications} />
<Tab.Screen name='Tab-Me' component={TabMe} listeners={meListeners} />
</Tab.Navigator>
)
}
export default ScreenTabs

View File

@@ -3,22 +3,17 @@ import TimelineDefault from '@components/Timeline/Default'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import React from 'react'
const TabMeBookmarks = React.memo(
() => {
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Bookmarks' }]
const TabMeBookmarks = () => {
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Bookmarks' }]
return (
<Timeline
queryKey={queryKey}
customProps={{
renderItem: ({ item }) => (
<TimelineDefault item={item} queryKey={queryKey} />
)
}}
/>
)
},
() => true
)
return (
<Timeline
queryKey={queryKey}
customProps={{
renderItem: ({ item }) => <TimelineDefault item={item} queryKey={queryKey} />
}}
/>
)
}
export default TabMeBookmarks

View File

@@ -3,22 +3,17 @@ import TimelineConversation from '@components/Timeline/Conversation'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import React from 'react'
const TabMeConversations = React.memo(
() => {
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Conversations' }]
const TabMeConversations = () => {
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Conversations' }]
return (
<Timeline
queryKey={queryKey}
customProps={{
renderItem: ({ item }) => (
<TimelineConversation conversation={item} queryKey={queryKey} />
)
}}
/>
)
},
() => true
)
return (
<Timeline
queryKey={queryKey}
customProps={{
renderItem: ({ item }) => <TimelineConversation conversation={item} queryKey={queryKey} />
}}
/>
)
}
export default TabMeConversations

View File

@@ -3,22 +3,17 @@ import TimelineDefault from '@components/Timeline/Default'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import React from 'react'
const TabMeFavourites = React.memo(
() => {
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Favourites' }]
const TabMeFavourites = () => {
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Favourites' }]
return (
<Timeline
queryKey={queryKey}
customProps={{
renderItem: ({ item }) => (
<TimelineDefault item={item} queryKey={queryKey} />
)
}}
/>
)
},
() => true
)
return (
<Timeline
queryKey={queryKey}
customProps={{
renderItem: ({ item }) => <TimelineDefault item={item} queryKey={queryKey} />
}}
/>
)
}
export default TabMeFavourites

View File

@@ -12,65 +12,62 @@ export interface Props {
account: Mastodon.Account | undefined
}
const AccountNav = React.memo(
({ scrollY, account }: Props) => {
const { colors } = useTheme()
const headerHeight = useSafeAreaInsets().top + 44
const AccountNav: React.FC<Props> = ({ scrollY, account }) => {
const { colors } = useTheme()
const headerHeight = useSafeAreaInsets().top + 44
const nameY =
Dimensions.get('window').width / 3 +
StyleConstants.Avatar.L -
StyleConstants.Spacing.Global.PagePadding * 2 +
StyleConstants.Spacing.M -
headerHeight
const nameY =
Dimensions.get('window').width / 3 +
StyleConstants.Avatar.L -
StyleConstants.Spacing.Global.PagePadding * 2 +
StyleConstants.Spacing.M -
headerHeight
const styleOpacity = useAnimatedStyle(() => {
return {
opacity: interpolate(scrollY.value, [0, 200], [0, 1], Extrapolate.CLAMP)
}
})
const styleMarginTop = useAnimatedStyle(() => {
return {
marginTop: interpolate(scrollY.value, [nameY, nameY + 20], [50, 0], Extrapolate.CLAMP)
}
})
const styleOpacity = useAnimatedStyle(() => {
return {
opacity: interpolate(scrollY.value, [0, 200], [0, 1], Extrapolate.CLAMP)
}
})
const styleMarginTop = useAnimatedStyle(() => {
return {
marginTop: interpolate(scrollY.value, [nameY, nameY + 20], [50, 0], Extrapolate.CLAMP)
}
})
return (
<Animated.View
style={[
styleOpacity,
{
...StyleSheet.absoluteFillObject,
zIndex: 99,
backgroundColor: colors.backgroundDefault,
height: headerHeight
}
]}
return (
<Animated.View
style={[
styleOpacity,
{
...StyleSheet.absoluteFillObject,
zIndex: 99,
backgroundColor: colors.backgroundDefault,
height: headerHeight
}
]}
>
<View
style={{
flex: 1,
alignItems: 'center',
overflow: 'hidden',
marginTop: useSafeAreaInsets().top + (44 - StyleConstants.Font.Size.L) / 2
}}
>
<View
style={{
flex: 1,
alignItems: 'center',
overflow: 'hidden',
marginTop: useSafeAreaInsets().top + (44 - StyleConstants.Font.Size.L) / 2
}}
>
<Animated.View style={[{ flexDirection: 'row' }, styleMarginTop]}>
{account ? (
<CustomText numberOfLines={1}>
<ParseEmojis
content={account.display_name || account.username}
emojis={account.emojis}
fontBold
/>
</CustomText>
) : null}
</Animated.View>
</View>
</Animated.View>
)
},
(_, next) => next.account === undefined
)
<Animated.View style={[{ flexDirection: 'row' }, styleMarginTop]}>
{account ? (
<CustomText numberOfLines={1}>
<ParseEmojis
content={account.display_name || account.username}
emojis={account.emojis}
fontBold
/>
</CustomText>
) : null}
</Animated.View>
</View>
</Animated.View>
)
}
export default AccountNav