use KeyboardStickyView from r-n-keyboard-controller

This commit is contained in:
Samuel Newman
2024-04-16 23:53:09 +01:00
parent a5a85a6202
commit 426c812904
3 changed files with 232 additions and 202 deletions
+3
View File
@@ -4,6 +4,7 @@ import 'view/icons'
import React, {useEffect, useState} from 'react' import React, {useEffect, useState} from 'react'
import {GestureHandlerRootView} from 'react-native-gesture-handler' import {GestureHandlerRootView} from 'react-native-gesture-handler'
import {KeyboardProvider} from 'react-native-keyboard-controller'
import {RootSiblingParent} from 'react-native-root-siblings' import {RootSiblingParent} from 'react-native-root-siblings'
import { import {
initialWindowMetrics, initialWindowMetrics,
@@ -156,7 +157,9 @@ function App() {
<LightboxStateProvider> <LightboxStateProvider>
<I18nProvider> <I18nProvider>
<PortalProvider> <PortalProvider>
<KeyboardProvider>
<InnerApp /> <InnerApp />
</KeyboardProvider>
</PortalProvider> </PortalProvider>
</I18nProvider> </I18nProvider>
</LightboxStateProvider> </LightboxStateProvider>
+11 -18
View File
@@ -43,14 +43,13 @@ import {useComposerControls} from '#/state/shell/composer'
import {useAnalytics} from 'lib/analytics/analytics' import {useAnalytics} from 'lib/analytics/analytics'
import * as apilib from 'lib/api/index' import * as apilib from 'lib/api/index'
import {MAX_GRAPHEME_LENGTH} from 'lib/constants' import {MAX_GRAPHEME_LENGTH} from 'lib/constants'
import {useIsKeyboardVisible} from 'lib/hooks/useIsKeyboardVisible'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {cleanError} from 'lib/strings/errors' import {cleanError} from 'lib/strings/errors'
import {insertMentionAt} from 'lib/strings/mention-manip' import {insertMentionAt} from 'lib/strings/mention-manip'
import {shortenLinks} from 'lib/strings/rich-text-manip' import {shortenLinks} from 'lib/strings/rich-text-manip'
import {colors, gradients, s} from 'lib/styles' import {colors, gradients, s} from 'lib/styles'
import {isAndroid, isIOS, isNative, isWeb} from 'platform/detection' import {isNative, isWeb} from 'platform/detection'
import {useDialogStateControlContext} from 'state/dialogs' import {useDialogStateControlContext} from 'state/dialogs'
import {GalleryModel} from 'state/models/media/gallery' import {GalleryModel} from 'state/models/media/gallery'
import {ComposerOpts} from 'state/shell/composer' import {ComposerOpts} from 'state/shell/composer'
@@ -66,6 +65,7 @@ import {UserAvatar} from '../util/UserAvatar'
import {CharProgress} from './char-progress/CharProgress' import {CharProgress} from './char-progress/CharProgress'
import {ExternalEmbed} from './ExternalEmbed' import {ExternalEmbed} from './ExternalEmbed'
import {GifAltText} from './GifAltText' import {GifAltText} from './GifAltText'
import {KeyboardAccessory} from './KeyboardAccessory'
import {LabelsBtn} from './labels/LabelsBtn' import {LabelsBtn} from './labels/LabelsBtn'
import {Gallery} from './photos/Gallery' import {Gallery} from './photos/Gallery'
import {OpenCameraBtn} from './photos/OpenCameraBtn' import {OpenCameraBtn} from './photos/OpenCameraBtn'
@@ -112,7 +112,6 @@ export const ComposePost = observer(function ComposePost({
const discardPromptControl = Prompt.usePromptControl() const discardPromptControl = Prompt.usePromptControl()
const {closeAllDialogs} = useDialogStateControlContext() const {closeAllDialogs} = useDialogStateControlContext()
const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true})
const [isProcessing, setIsProcessing] = useState(false) const [isProcessing, setIsProcessing] = useState(false)
const [processingState, setProcessingState] = useState('') const [processingState, setProcessingState] = useState('')
const [error, setError] = useState('') const [error, setError] = useState('')
@@ -150,11 +149,10 @@ export const ComposePost = observer(function ComposePost({
const insets = useSafeAreaInsets() const insets = useSafeAreaInsets()
const viewStyles = useMemo( const viewStyles = useMemo(
() => ({ () => ({
paddingBottom: paddingBottom: isNative ? insets.bottom + 80 : 0,
isAndroid || (isIOS && !isKeyboardVisible) ? insets.bottom : 0,
paddingTop: isMobile && isWeb ? 15 : 0, paddingTop: isMobile && isWeb ? 15 : 0,
}), }),
[insets, isKeyboardVisible, isMobile], [insets, isMobile],
) )
const onPressCancel = useCallback(() => { const onPressCancel = useCallback(() => {
@@ -355,6 +353,7 @@ export const ComposePost = observer(function ComposePost({
) )
return ( return (
<>
<KeyboardAvoidingView <KeyboardAvoidingView
testID="composePostView" testID="composePostView"
behavior={Platform.OS === 'ios' ? 'padding' : 'height'} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
@@ -521,7 +520,10 @@ export const ComposePost = observer(function ComposePost({
) : undefined} ) : undefined}
</ScrollView> </ScrollView>
<SuggestedLanguage text={richtext.text} /> <SuggestedLanguage text={richtext.text} />
<View style={[pal.border, styles.bottomBar]}> </View>
</KeyboardAvoidingView>
<KeyboardAccessory>
<View style={[a.flex_row, a.align_center, a.gap_xs]}> <View style={[a.flex_row, a.align_center, a.gap_xs]}>
<SelectPhotoBtn gallery={gallery} disabled={!canSelectImages} /> <SelectPhotoBtn gallery={gallery} disabled={!canSelectImages} />
<OpenCameraBtn gallery={gallery} disabled={!canSelectImages} /> <OpenCameraBtn gallery={gallery} disabled={!canSelectImages} />
@@ -546,8 +548,7 @@ export const ComposePost = observer(function ComposePost({
<View style={s.flex1} /> <View style={s.flex1} />
<SelectLangBtn /> <SelectLangBtn />
<CharProgress count={graphemeLength} /> <CharProgress count={graphemeLength} />
</View> </KeyboardAccessory>
</View>
<Prompt.Basic <Prompt.Basic
control={discardPromptControl} control={discardPromptControl}
@@ -557,7 +558,7 @@ export const ComposePost = observer(function ComposePost({
confirmButtonCta={_(msg`Discard`)} confirmButtonCta={_(msg`Discard`)}
confirmButtonColor="negative" confirmButtonColor="negative"
/> />
</KeyboardAvoidingView> </>
) )
}) })
@@ -639,12 +640,4 @@ const styles = StyleSheet.create({
marginHorizontal: 10, marginHorizontal: 10,
marginBottom: 4, marginBottom: 4,
}, },
bottomBar: {
flexDirection: 'row',
paddingVertical: 4,
paddingLeft: 15,
paddingRight: 20,
alignItems: 'center',
borderTopWidth: 1,
},
}) })
@@ -0,0 +1,34 @@
import React from 'react'
import {View} from 'react-native'
import {KeyboardStickyView} from 'react-native-keyboard-controller'
import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {isWeb} from '#/platform/detection'
import {atoms as a, useTheme} from '#/alf'
export function KeyboardAccessory({children}: {children: React.ReactNode}) {
const t = useTheme()
const {bottom} = useSafeAreaInsets()
const style = [
a.flex_row,
{paddingVertical: 10},
a.pl_lg,
a.pr_xl,
a.align_center,
a.border_t,
t.atoms.border_contrast_medium,
t.atoms.bg,
]
// todo: when iPad support is added, it should also not use the KeyboardStickyView
if (isWeb) {
return <View style={style}>{children}</View>
}
return (
<KeyboardStickyView offset={{closed: -bottom}} style={style}>
{children}
</KeyboardStickyView>
)
}