This commit is contained in:
Zhiyuan Zheng 2021-03-18 23:32:31 +01:00
parent e1f95ea2b2
commit f9f9b783e3
No known key found for this signature in database
GPG Key ID: 078A93AB607D85E0
9 changed files with 123 additions and 105 deletions

View File

@ -23,7 +23,7 @@ const HeaderCenter = React.memo(
/>
)
},
() => true
(prev, next) => prev.content === next.content
)
const styles = StyleSheet.create({

View File

@ -340,6 +340,12 @@ const ScreenCompose: React.FC<ScreenComposeProp> = ({
[totalTextCount, composeState]
)
const headerContent = useMemo(() => {
return `${totalTextCount} / ${maxTootChars}${
__DEV__ ? ` Dirty: ${composeState.dirty.toString()}` : ''
}`
}, [totalTextCount, maxTootChars, composeState.dirty])
return (
<KeyboardAvoidingView
style={styles.base}
@ -358,26 +364,26 @@ const ScreenCompose: React.FC<ScreenComposeProp> = ({
name='Screen-Compose-Root'
component={ComposeRoot}
options={{
...Platform.select({
ios: {
headerTitle: headerContent,
headerTitleStyle: {
fontWeight:
totalTextCount > maxTootChars
? StyleConstants.Font.Weight.Bold
: StyleConstants.Font.Weight.Normal,
fontSize: StyleConstants.Font.Size.M
},
headerTintColor:
totalTextCount > maxTootChars
? theme.red
: theme.secondary
},
android: {
headerCenter: () => <HeaderCenter content={headerContent} />
}
}),
headerLeft,
headerTitle: `${totalTextCount} / ${maxTootChars}${
__DEV__ ? ` Dirty: ${composeState.dirty.toString()}` : ''
}`,
headerTitleStyle: {
fontWeight:
totalTextCount > maxTootChars
? StyleConstants.Font.Weight.Bold
: StyleConstants.Font.Weight.Normal,
fontSize: StyleConstants.Font.Size.M
},
headerTintColor:
totalTextCount > maxTootChars ? theme.red : theme.secondary,
headerCenter: () => (
<HeaderCenter
content={`${totalTextCount} / ${maxTootChars}${
__DEV__ ? ` Dirty: ${composeState.dirty.toString()}` : ''
}`}
/>
),
headerRight
}}
/>

View File

@ -1,7 +1,7 @@
import AttachmentVideo from '@components/Timeline/Shared/Attachment/Video'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useContext, useMemo } from 'react'
import React, { useContext, useMemo, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { ScrollView, StyleSheet, Text, TextInput, View } from 'react-native'
import ComposeContext from '../utils/createContext'
@ -55,8 +55,10 @@ const ComposeEditAttachmentRoot: React.FC<Props> = ({ index }) => {
}
})
const scrollViewRef = useRef<ScrollView>(null)
return (
<ScrollView>
<ScrollView ref={scrollViewRef}>
{mediaDisplay}
<View style={styles.altTextContainer}>
<Text style={[styles.altTextInputHeading, { color: theme.primary }]}>
@ -67,6 +69,7 @@ const ComposeEditAttachmentRoot: React.FC<Props> = ({ index }) => {
styles.altTextInput,
{ borderColor: theme.border, color: theme.primary }
]}
onFocus={() => scrollViewRef.current?.scrollToEnd()}
autoCapitalize='none'
autoCorrect={false}
maxLength={1500}

View File

@ -4,7 +4,13 @@ import { useSearchQuery } from '@utils/queryHooks/search'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import { forEach, groupBy, sortBy } from 'lodash'
import React, { useCallback, useContext, useEffect, useMemo } from 'react'
import React, {
useCallback,
useContext,
useEffect,
useMemo,
useRef
} from 'react'
import { FlatList, Image, StyleSheet, View } from 'react-native'
import { Circle } from 'react-native-animated-spinkit'
import ComposeActions from './Root/Actions'
@ -30,90 +36,93 @@ const prefetchEmojis = (
})
}
const ComposeRoot: React.FC = () => {
const { theme } = useTheme()
const ComposeRoot = React.memo(
() => {
const { theme } = useTheme()
const { composeState, composeDispatch } = useContext(ComposeContext)
const { composeState, composeDispatch } = useContext(ComposeContext)
const { isFetching, data, refetch } = useSearchQuery({
type:
composeState.tag?.type === 'accounts' ||
composeState.tag?.type === 'hashtags'
? composeState.tag.type
: undefined,
term: composeState.tag?.text.substring(1),
options: { enabled: false }
})
const { isFetching, data, refetch } = useSearchQuery({
type:
composeState.tag?.type === 'accounts' ||
composeState.tag?.type === 'hashtags'
? composeState.tag.type
: undefined,
term: composeState.tag?.text.substring(1),
options: { enabled: false }
})
useEffect(() => {
if (
(composeState.tag?.type === 'accounts' ||
composeState.tag?.type === 'hashtags') &&
composeState.tag?.text
) {
refetch()
}
}, [composeState.tag])
useEffect(() => {
if (
(composeState.tag?.type === 'accounts' ||
composeState.tag?.type === 'hashtags') &&
composeState.tag?.text
) {
refetch()
}
}, [composeState.tag])
const { data: emojisData } = useEmojisQuery({})
useEffect(() => {
if (emojisData && emojisData.length) {
let sortedEmojis: { title: string; data: Mastodon.Emoji[] }[] = []
forEach(
groupBy(sortBy(emojisData, ['category', 'shortcode']), 'category'),
(value, key) => sortedEmojis.push({ title: key, data: value })
)
composeDispatch({
type: 'emoji',
payload: { ...composeState.emoji, emojis: sortedEmojis }
})
prefetchEmojis(sortedEmojis)
}
}, [emojisData])
const { data: emojisData } = useEmojisQuery({})
useEffect(() => {
if (emojisData && emojisData.length) {
let sortedEmojis: { title: string; data: Mastodon.Emoji[] }[] = []
forEach(
groupBy(sortBy(emojisData, ['category', 'shortcode']), 'category'),
(value, key) => sortedEmojis.push({ title: key, data: value })
)
composeDispatch({
type: 'emoji',
payload: { ...composeState.emoji, emojis: sortedEmojis }
})
prefetchEmojis(sortedEmojis)
}
}, [emojisData])
const listEmpty = useMemo(() => {
if (isFetching) {
return (
<View key='listEmpty' style={styles.loading}>
<Circle
size={StyleConstants.Font.Size.M * 1.25}
color={theme.secondary}
/>
</View>
)
}
}, [isFetching])
const listEmpty = useMemo(() => {
if (isFetching) {
return (
<View key='listEmpty' style={styles.loading}>
<Circle
size={StyleConstants.Font.Size.M * 1.25}
color={theme.secondary}
/>
</View>
)
}
}, [isFetching])
const listItem = useCallback(
({ item }) => (
<ComposeRootSuggestion
item={item}
composeState={composeState}
composeDispatch={composeDispatch}
/>
),
[composeState]
)
const listItem = useCallback(
({ item }) => (
<ComposeRootSuggestion
item={item}
composeState={composeState}
composeDispatch={composeDispatch}
/>
),
[composeState]
)
return (
<View style={styles.base}>
<FlatList
renderItem={listItem}
ListEmptyComponent={listEmpty}
keyboardShouldPersistTaps='handled'
ListHeaderComponent={ComposeRootHeader}
ListFooterComponent={ComposeRootFooter}
ItemSeparatorComponent={ComponentSeparator}
// @ts-ignore
data={data ? data[composeState.tag?.type] : undefined}
keyExtractor={() => Math.random().toString()}
/>
<ComposeActions />
<ComposeDrafts />
<ComposePosting />
</View>
)
}
return (
<View style={styles.base}>
<FlatList
renderItem={listItem}
ListEmptyComponent={listEmpty}
keyboardShouldPersistTaps='always'
ListHeaderComponent={ComposeRootHeader}
ListFooterComponent={ComposeRootFooter}
ItemSeparatorComponent={ComponentSeparator}
// @ts-ignore
data={data ? data[composeState.tag?.type] : undefined}
keyExtractor={() => Math.random().toString()}
/>
<ComposeActions />
<ComposeDrafts />
<ComposePosting />
</View>
)
},
() => true
)
const styles = StyleSheet.create({
base: {

View File

@ -246,7 +246,7 @@ const ComposeAttachments: React.FC = () => {
snapToAlignment='center'
renderItem={renderAttachment}
snapToOffsets={snapToOffsets}
keyboardShouldPersistTaps='handled'
keyboardShouldPersistTaps='always'
showsHorizontalScrollIndicator={false}
data={composeState.attachments.uploads}
keyExtractor={item =>

View File

@ -76,7 +76,7 @@ const ComposeEmojis: React.FC = () => {
<View style={styles.base}>
<SectionList
horizontal
keyboardShouldPersistTaps='handled'
keyboardShouldPersistTaps='always'
sections={composeState.emoji.emojis || []}
keyExtractor={item => item.shortcode}
renderSectionHeader={listHeader}

View File

@ -46,7 +46,7 @@ const ComposeSpoilerInput: React.FC = () => {
})
}}
ref={composeState.textInputFocus.refs.spoiler}
scrollEnabled
scrollEnabled={false}
onFocus={() =>
composeDispatch({
type: 'textInputFocus',

View File

@ -52,7 +52,7 @@ const ComposeTextInput: React.FC = () => {
})
}}
ref={composeState.textInputFocus.refs.text}
scrollEnabled
scrollEnabled={false}
>
<Text>{composeState.text.formatted}</Text>
</TextInput>

View File

@ -54,7 +54,7 @@ const ScreenMeSwitchRoot: React.FC = () => {
const instanceActive = useSelector(getInstanceActive)
return (
<ScrollView style={styles.base} keyboardShouldPersistTaps='handled'>
<ScrollView style={styles.base} keyboardShouldPersistTaps='always'>
<View style={[styles.firstSection, { borderBottomColor: theme.border }]}>
<Text style={[styles.header, { color: theme.primary }]}>
{t('content.existing')}