Fix safe area view and keyboard view

This commit is contained in:
Zhiyuan Zheng 2020-11-15 23:33:01 +01:00
parent 188b97fbd8
commit 5cf6eaa8d9
No known key found for this signature in database
GPG Key ID: 078A93AB607D85E0
3 changed files with 245 additions and 257 deletions

View File

@ -7,7 +7,6 @@ import React from 'react'
import { Feather } from '@expo/vector-icons'
import store from 'src/stacks/common/store'
import { Provider } from 'react-redux'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import Toast from 'react-native-toast-message'
import { StatusBar } from 'expo-status-bar'
@ -25,7 +24,6 @@ export const Index: React.FC = () => {
<Provider store={store}>
<StatusBar style='auto' />
<SafeAreaProvider>
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
@ -84,7 +82,6 @@ export const Index: React.FC = () => {
<Toast ref={(ref: any) => Toast.setRef(ref)} />
</NavigationContainer>
</SafeAreaProvider>
</Provider>
)
}

View File

@ -1,5 +1,12 @@
import React, { ReactNode, useReducer } from 'react'
import { Alert, Pressable, Text } from 'react-native'
import React, { ReactNode, useEffect, useReducer, useState } from 'react'
import {
Alert,
Keyboard,
KeyboardAvoidingView,
Pressable,
Text
} from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context'
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
import { useNavigation } from '@react-navigation/native'
@ -24,11 +31,6 @@ export type PostState = {
}
| undefined
emojis: mastodon.Emoji[] | undefined
height: {
view: number
editor: number
keyboard: number
}
}
export type PostAction =
@ -52,10 +54,6 @@ export type PostAction =
type: 'emojis'
payload: PostState['emojis']
}
| {
type: 'height'
payload: Partial<PostState['height']>
}
const postInitialState: PostState = {
text: {
@ -66,12 +64,7 @@ const postInitialState: PostState = {
selection: { start: 0, end: 0 },
overlay: null,
tag: undefined,
emojis: undefined,
height: {
view: 0,
editor: 0,
keyboard: 0
}
emojis: undefined
}
const postReducer = (state: PostState, action: PostAction): PostState => {
switch (action.type) {
@ -85,8 +78,6 @@ const postReducer = (state: PostState, action: PostAction): PostState => {
return { ...state, tag: action.payload }
case 'emojis':
return { ...state, emojis: action.payload }
case 'height':
return { ...state, height: { ...state.height, ...action.payload } }
default:
throw new Error('Unexpected action')
}
@ -95,9 +86,32 @@ const postReducer = (state: PostState, action: PostAction): PostState => {
const PostToot: React.FC = () => {
const navigation = useNavigation()
const [hasKeyboard, setHasKeyboard] = useState(false)
useEffect(() => {
Keyboard.addListener('keyboardWillShow', _keyboardDidShow)
Keyboard.addListener('keyboardWillHide', _keyboardDidHide)
// cleanup function
return () => {
Keyboard.removeListener('keyboardWillShow', _keyboardDidShow)
Keyboard.removeListener('keyboardWillHide', _keyboardDidHide)
}
}, [])
const _keyboardDidShow = () => {
setHasKeyboard(true)
}
const _keyboardDidHide = () => {
setHasKeyboard(false)
}
const [postState, postDispatch] = useReducer(postReducer, postInitialState)
return (
<KeyboardAvoidingView behavior='padding' style={{ flex: 1 }}>
<SafeAreaView
style={{ flex: 1 }}
edges={hasKeyboard ? ['left', 'right'] : ['left', 'right', 'bottom']}
>
<Stack.Navigator>
<Stack.Screen
name='PostMain'
@ -166,6 +180,8 @@ const PostToot: React.FC = () => {
)}
</Stack.Screen>
</Stack.Navigator>
</SafeAreaView>
</KeyboardAvoidingView>
)
}

View File

@ -1,4 +1,10 @@
import React, { createElement, Dispatch, useCallback, useEffect } from 'react'
import React, {
createElement,
Dispatch,
useCallback,
useEffect,
useState
} from 'react'
import {
Keyboard,
Pressable,
@ -7,7 +13,6 @@ import {
TextInput,
View
} from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context'
import { Feather } from '@expo/vector-icons'
import { debounce, differenceWith, isEqual } from 'lodash'
@ -24,27 +29,7 @@ export interface Props {
}
const PostMain: React.FC<Props> = ({ postState, postDispatch }) => {
useEffect(() => {
Keyboard.addListener('keyboardDidShow', _keyboardDidShow)
Keyboard.addListener('keyboardDidHide', _keyboardDidHide)
return () => {
Keyboard.removeListener('keyboardDidShow', _keyboardDidShow)
Keyboard.removeListener('keyboardDidHide', _keyboardDidHide)
}
}, [])
const _keyboardDidShow = (props: any) => {
postDispatch({
type: 'height',
payload: { keyboard: props.endCoordinates.height }
})
}
const _keyboardDidHide = () => {
postDispatch({
type: 'height',
payload: { keyboard: 0 }
})
}
const [editorMinHeight, setEditorMinHeight] = useState(0)
const { data: emojisData } = useQuery(['Emojis'], emojisFetch)
useEffect(() => {
@ -54,15 +39,10 @@ const PostMain: React.FC<Props> = ({ postState, postDispatch }) => {
}, [emojisData])
const debouncedSuggestions = useCallback(
debounce(
tag =>
(() => {
console.log(tag)
debounce(tag => {
postDispatch({ type: 'overlay', payload: 'suggestions' })
postDispatch({ type: 'tag', payload: tag })
})(),
300
),
}, 500),
[]
)
let prevTags: PostState['tag'][] = []
@ -87,7 +67,6 @@ const PostMain: React.FC<Props> = ({ postState, postDispatch }) => {
newType = 'url'
break
}
// @ts-ignore
tags.push({
type: newType,
text: props.getMatchedText(),
@ -99,7 +78,18 @@ const PostMain: React.FC<Props> = ({ postState, postDispatch }) => {
const changedTag = differenceWith(prevTags, tags, isEqual)
// quick delete causes flicking of suggestion box
if (changedTag.length && tags.length && !disableDebounce) {
if (
changedTag.length > 0 &&
tags.length > 0 &&
content.length > 0 &&
!disableDebounce
) {
console.log('changedTag length')
console.log(changedTag.length)
console.log('tags length')
console.log(tags.length)
console.log('changed Tag')
console.log(changedTag)
if (changedTag[0]!.type !== 'url') {
debouncedSuggestions(changedTag[0])
}
@ -147,26 +137,15 @@ const PostMain: React.FC<Props> = ({ postState, postDispatch }) => {
}
})
}, [])
return (
<SafeAreaView
style={styles.main}
edges={['left', 'right', 'bottom']}
onLayout={({ nativeEvent }) =>
postDispatch({
type: 'height',
payload: { view: nativeEvent.layout.height }
})
}
>
<View
style={{ height: postState.height.view - postState.height.keyboard }}
>
<View style={{ flex: 1 }}>
<TextInput
style={[
styles.textInput,
{
flex: postState.overlay ? 0 : 1,
minHeight: postState.height.editor + 14
minHeight: editorMinHeight + 14
}
]}
autoCapitalize='none'
@ -177,10 +156,7 @@ const PostMain: React.FC<Props> = ({ postState, postDispatch }) => {
placeholder='想说点什么'
onChangeText={content => onChangeText({ content })}
onContentSizeChange={({ nativeEvent }) => {
postDispatch({
type: 'height',
payload: { editor: nativeEvent.contentSize.height }
})
setEditorMinHeight(nativeEvent.contentSize.height)
}}
onSelectionChange={({
nativeEvent: {
@ -232,7 +208,6 @@ const PostMain: React.FC<Props> = ({ postState, postDispatch }) => {
<Text>{postState.text.count}</Text>
</Pressable>
</View>
</SafeAreaView>
)
}