Fix visibility of the mentions autocomplete in the composer (#326) (#329)

* Improve layout in composer to ensure the mentions autocomplete is visible (closes #326)

* Dont dismiss the keyboard in the composer
zio/stable
Paul Frazee 2023-03-20 16:10:29 -05:00 committed by GitHub
parent df6a712834
commit 8a3601c07c
3 changed files with 67 additions and 50 deletions

View File

@ -32,6 +32,7 @@ import {SelectedPhotos} from './photos/SelectedPhotos'
import {usePalette} from 'lib/hooks/usePalette'
import QuoteEmbed from '../util/PostEmbeds/QuoteEmbed'
import {useExternalLinkFetch} from './useExternalLinkFetch'
import {isDesktopWeb} from 'platform/detection'
const MAX_TEXT_LENGTH = 256
@ -188,10 +189,6 @@ export const ComposePost = observer(function ComposePost({
const canPost = text.length <= MAX_TEXT_LENGTH
const selectTextInputLayout =
selectedPhotos.length !== 0
? styles.textInputLayoutWithPhoto
: styles.textInputLayoutWithoutPhoto
const selectTextInputPlaceholder = replyTo
? 'Write your reply'
: selectedPhotos.length !== 0
@ -253,7 +250,9 @@ export const ComposePost = observer(function ComposePost({
<Text style={[s.red4, s.flex1]}>{error}</Text>
</View>
)}
<ScrollView style={s.flex1}>
<ScrollView
style={styles.scrollView}
keyboardShouldPersistTaps="always">
{replyTo ? (
<View style={[pal.border, styles.replyToLayout]}>
<UserAvatar avatar={replyTo.author.avatar} size={50} />
@ -268,12 +267,7 @@ export const ComposePost = observer(function ComposePost({
</View>
) : undefined}
<View
style={[
pal.border,
styles.textInputLayout,
selectTextInputLayout,
]}>
<View style={[pal.border, styles.textInputLayout]}>
<UserAvatar avatar={store.me.avatar} size={50} />
<TextInput
ref={textInput}
@ -346,14 +340,14 @@ const styles = StyleSheet.create({
outer: {
flexDirection: 'column',
flex: 1,
padding: 15,
height: '100%',
},
topbar: {
flexDirection: 'row',
alignItems: 'center',
paddingTop: isDesktopWeb ? 10 : undefined,
paddingBottom: 10,
paddingHorizontal: 5,
paddingHorizontal: 20,
height: 55,
},
postBtn: {
@ -365,12 +359,14 @@ const styles = StyleSheet.create({
borderRadius: 6,
paddingHorizontal: 8,
paddingVertical: 6,
marginHorizontal: 15,
marginBottom: 6,
},
errorLine: {
flexDirection: 'row',
backgroundColor: colors.red1,
borderRadius: 6,
marginHorizontal: 15,
paddingHorizontal: 8,
paddingVertical: 6,
marginVertical: 6,
@ -386,13 +382,12 @@ const styles = StyleSheet.create({
justifyContent: 'center',
marginRight: 5,
},
textInputLayoutWithPhoto: {
flexWrap: 'wrap',
},
textInputLayoutWithoutPhoto: {
scrollView: {
flex: 1,
paddingHorizontal: 15,
},
textInputLayout: {
flex: isDesktopWeb ? undefined : 1,
flexDirection: 'row',
borderTopWidth: 1,
paddingTop: 16,
@ -418,7 +413,8 @@ const styles = StyleSheet.create({
bottomBar: {
flexDirection: 'row',
paddingVertical: 10,
paddingRight: 5,
paddingLeft: 15,
paddingRight: 20,
alignItems: 'center',
borderTopWidth: 1,
},

View File

@ -3,6 +3,7 @@ import {
NativeSyntheticEvent,
StyleSheet,
TextInputSelectionChangeEventData,
View,
} from 'react-native'
import PasteInput, {
PastedFile,
@ -185,7 +186,7 @@ export const TextInput = React.forwardRef(
}, [text, pal.link, pal.text])
return (
<>
<View style={styles.container}>
<PasteInput
testID="composerTextInput"
ref={textInput}
@ -202,15 +203,20 @@ export const TextInput = React.forwardRef(
view={autocompleteView}
onSelect={onSelectAutocompleteItem}
/>
</>
</View>
)
},
)
const styles = StyleSheet.create({
container: {
width: '100%',
},
textInput: {
flex: 1,
minHeight: 80,
padding: 5,
paddingBottom: 20,
marginLeft: 8,
alignSelf: 'flex-start',
},

View File

@ -1,10 +1,5 @@
import React, {useEffect} from 'react'
import {
Animated,
TouchableOpacity,
StyleSheet,
useWindowDimensions,
} from 'react-native'
import {Animated, TouchableOpacity, StyleSheet, View} from 'react-native'
import {observer} from 'mobx-react-lite'
import {UserAutocompleteViewModel} from 'state/models/user-autocomplete-view'
import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
@ -20,52 +15,72 @@ export const Autocomplete = observer(
onSelect: (item: string) => void
}) => {
const pal = usePalette('default')
const winDim = useWindowDimensions()
const positionInterp = useAnimatedValue(0)
useEffect(() => {
Animated.timing(positionInterp, {
toValue: view.isActive ? 1 : 0,
duration: 200,
useNativeDriver: false,
useNativeDriver: true,
}).start()
}, [positionInterp, view.isActive])
const topAnimStyle = {
top: positionInterp.interpolate({
inputRange: [0, 1],
outputRange: [winDim.height, winDim.height / 4],
}),
transform: [
{
translateY: positionInterp.interpolate({
inputRange: [0, 1],
outputRange: [200, 0],
}),
},
],
}
return (
<Animated.View style={[styles.outer, pal.view, pal.border, topAnimStyle]}>
{view.suggestions.map(item => (
<TouchableOpacity
testID="autocompleteButton"
key={item.handle}
style={[pal.border, styles.item]}
onPress={() => onSelect(item.handle)}>
<Text type="md-medium" style={pal.text}>
{item.displayName || item.handle}
<Text type="sm" style={pal.textLight}>
&nbsp;@{item.handle}
<View style={[styles.container, view.isActive && styles.visible]}>
<Animated.View
style={[
styles.animatedContainer,
pal.view,
pal.border,
topAnimStyle,
view.isActive && styles.visible,
]}>
{view.suggestions.slice(0, 5).map(item => (
<TouchableOpacity
testID="autocompleteButton"
key={item.handle}
style={[pal.border, styles.item]}
onPress={() => onSelect(item.handle)}>
<Text type="md-medium" style={pal.text}>
{item.displayName || item.handle}
<Text type="sm" style={pal.textLight}>
&nbsp;@{item.handle}
</Text>
</Text>
</Text>
</TouchableOpacity>
))}
</Animated.View>
</TouchableOpacity>
))}
</Animated.View>
</View>
)
},
)
const styles = StyleSheet.create({
outer: {
container: {
display: 'none',
height: 250,
},
animatedContainer: {
display: 'none',
position: 'absolute',
left: 0,
left: -64,
right: 0,
bottom: 0,
top: 0,
borderTopWidth: 1,
},
visible: {
display: 'flex',
},
item: {
borderBottomWidth: 1,
paddingVertical: 16,