Remove flat list in compose view

This commit is contained in:
xmflsct 2023-01-01 13:39:48 +01:00
parent 554825a9ea
commit ac9738d358
4 changed files with 149 additions and 115 deletions

View File

@ -141,6 +141,9 @@ const ComposeActions: React.FC = () => {
<View
accessibilityRole='toolbar'
style={{
position: 'absolute',
bottom: 0,
width: '100%',
height: 45,
borderTopWidth: StyleSheet.hairlineWidth,
flexDirection: 'row',

View File

@ -1,53 +0,0 @@
import ComponentAccount from '@components/Account'
import haptics from '@components/haptics'
import ComponentHashtag from '@components/Hashtag'
import React, { useContext, useEffect } from 'react'
import ComposeContext from '../utils/createContext'
import { formatText } from '../utils/processText'
type Props = { item: Mastodon.Account & Mastodon.Tag }
const ComposeRootSuggestion: React.FC<Props> = ({ item }) => {
const { composeState, composeDispatch } = useContext(ComposeContext)
useEffect(() => {
if (composeState.text.raw.length === 0) {
composeDispatch({ type: 'tag', payload: undefined })
}
}, [composeState.text.raw.length])
const onPress = () => {
const focusedInput = composeState.textInputFocus.current
const updatedText = (): string => {
const main = item.acct ? `@${item.acct}` : `#${item.name}`
const textInput = composeState.textInputFocus.current
if (composeState.tag) {
const contentFront = composeState[textInput].raw.slice(0, composeState.tag.index)
const contentRear = composeState[textInput].raw.slice(composeState.tag.lastIndex)
const spaceFront =
composeState[textInput].raw.length === 0 || /\s/g.test(contentFront.slice(-1)) ? '' : ' '
const spaceRear = /\s/g.test(contentRear[0]) ? '' : ' '
return [contentFront, spaceFront, main, spaceRear, contentRear].join('')
} else {
return composeState[textInput].raw
}
}
formatText({
textInput: focusedInput,
composeDispatch,
content: updatedText(),
disableDebounce: true
})
haptics('Light')
}
return item.acct ? (
<ComponentAccount account={item} props={{ onPress }} />
) : (
<ComponentHashtag hashtag={item} onPress={onPress} />
)
}
export default ComposeRootSuggestion

View File

@ -0,0 +1,135 @@
import ComponentAccount from '@components/Account'
import haptics from '@components/haptics'
import ComponentHashtag from '@components/Hashtag'
import Icon from '@components/Icon'
import ComponentSeparator from '@components/Separator'
import { useSearchQuery } from '@utils/queryHooks/search'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { Fragment, useContext, useEffect } from 'react'
import { View } from 'react-native'
import { Circle } from 'react-native-animated-spinkit'
import ComposeContext from '../utils/createContext'
import { formatText } from '../utils/processText'
const ComposeRootSuggestions: React.FC = () => {
const { composeState, composeDispatch } = useContext(ComposeContext)
const { colors } = useTheme()
useEffect(() => {
if (composeState.text.raw.length === 0) {
composeDispatch({ type: 'tag', payload: undefined })
}
}, [composeState.text.raw.length])
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),
limit: 10,
options: { enabled: false }
})
useEffect(() => {
if (
(composeState.tag?.schema === '@' || composeState.tag?.schema === '#') &&
composeState.tag?.raw
) {
refetch()
}
}, [composeState.tag])
const onPress = (content: string) => {
const focusedInput = composeState.textInputFocus.current
const updatedText = (): string => {
const textInput = composeState.textInputFocus.current
if (composeState.tag) {
const contentFront = composeState[textInput].raw.slice(0, composeState.tag.index)
const contentRear = composeState[textInput].raw.slice(composeState.tag.lastIndex)
const spaceFront =
contentFront.length === 0 ||
composeState[textInput].raw.length === 0 ||
/\s/g.test(contentFront.slice(-1))
? ''
: ' '
const spaceRear = /\s/g.test(contentRear[0]) ? '' : ' '
return [contentFront, spaceFront, content, spaceRear, contentRear].join('')
} else {
return composeState[textInput].raw
}
}
formatText({
textInput: focusedInput,
composeDispatch,
content: updatedText(),
disableDebounce: true
})
haptics('Light')
}
const main = () => {
if (composeState.tag) {
switch (composeState.tag?.schema) {
case '@':
return (
<View>
{data?.accounts?.map(account => (
<Fragment key={account.id}>
<ComponentAccount
account={account}
props={{ onPress: () => onPress(`@${account.acct}`) }}
children={
<Icon
name='Plus'
size={StyleConstants.Font.Size.L}
color={colors.secondary}
style={{ marginLeft: 8 }}
/>
}
/>
<ComponentSeparator />
</Fragment>
))}
</View>
)
case '#':
return (
<View>
{data?.hashtags?.map(hashtag => (
<Fragment key={hashtag.name}>
<ComponentHashtag hashtag={hashtag} onPress={() => onPress(`#${hashtag.name}`)} />
<ComponentSeparator />
</Fragment>
))}
</View>
)
}
}
}
return isFetching ? (
<View
key='listEmpty'
style={{ flex: 1, alignItems: 'center', marginVertical: StyleConstants.Spacing.M }}
>
<Circle size={StyleConstants.Font.Size.M * 1.25} color={colors.secondary} />
</View>
) : (
<>{main()}</>
)
}
export default ComposeRootSuggestions

View File

@ -1,21 +1,13 @@
import ComponentSeparator from '@components/Separator'
import { useSearchQuery } from '@utils/queryHooks/search'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useContext, useEffect, useRef } from 'react'
import { AccessibilityInfo, findNodeHandle, FlatList, View } from 'react-native'
import { Circle } from 'react-native-animated-spinkit'
import React, { useEffect, useRef } from 'react'
import { AccessibilityInfo, findNodeHandle, ScrollView, View } from 'react-native'
import ComposePosting from '../Posting'
import ComposeContext from '../utils/createContext'
import ComposeActions from './Actions'
import ComposeDrafts from './Drafts'
import ComposeRootFooter from './Footer'
import ComposeRootHeader from './Header'
import ComposeRootSuggestion from './Suggestion'
import ComposeRootSuggestion from './Suggestions'
const ComposeRoot = () => {
const { colors } = useTheme()
const accessibleRefDrafts = useRef(null)
const accessibleRefAttachments = useRef(null)
@ -24,60 +16,17 @@ const ComposeRoot = () => {
tagDrafts && AccessibilityInfo.setAccessibilityFocus(tagDrafts)
}, [accessibleRefDrafts.current])
const { composeState } = useContext(ComposeContext)
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 }
})
useEffect(() => {
if (
(composeState.tag?.schema === '@' || composeState.tag?.schema === '#') &&
composeState.tag?.raw
) {
refetch()
}
}, [composeState.tag])
return (
<View style={{ flex: 1 }}>
<FlatList
renderItem={({ item }) => <ComposeRootSuggestion item={item} />}
ListEmptyComponent={
isFetching ? (
<View key='listEmpty' style={{ flex: 1, alignItems: 'center' }}>
<Circle size={StyleConstants.Font.Size.M * 1.25} color={colors.secondary} />
</View>
) : null
}
keyboardShouldPersistTaps='always'
ListHeaderComponent={ComposeRootHeader}
ListFooterComponent={
<ComposeRootFooter accessibleRefAttachments={accessibleRefAttachments} />
}
ItemSeparatorComponent={ComponentSeparator}
// @ts-ignore
data={data ? data[mapSchemaToType()] : undefined}
keyExtractor={() => Math.random().toString()}
/>
<ComposeActions />
<>
<ScrollView keyboardShouldPersistTaps='always' style={{ marginBottom: 50 }}>
<ComposeRootHeader />
<ComposeRootSuggestion />
<ComposeRootFooter accessibleRefAttachments={accessibleRefAttachments} />
</ScrollView>
<ComposeDrafts accessibleRefDrafts={accessibleRefDrafts} />
<ComposePosting />
</View>
<ComposeActions />
</>
)
}