diff --git a/src/App.native.tsx b/src/App.native.tsx
index 9fa82e9cdb..b60d024d5a 100644
--- a/src/App.native.tsx
+++ b/src/App.native.tsx
@@ -4,6 +4,7 @@ import 'view/icons'
import React, {useEffect, useState} from 'react'
import {GestureHandlerRootView} from 'react-native-gesture-handler'
+import {KeyboardProvider} from 'react-native-keyboard-controller'
import {RootSiblingParent} from 'react-native-root-siblings'
import {
initialWindowMetrics,
@@ -156,7 +157,9 @@ function App() {
-
+
+
+
diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx
index df4e5b9e3f..ca1bd23517 100644
--- a/src/view/com/composer/Composer.tsx
+++ b/src/view/com/composer/Composer.tsx
@@ -43,14 +43,13 @@ import {useComposerControls} from '#/state/shell/composer'
import {useAnalytics} from 'lib/analytics/analytics'
import * as apilib from 'lib/api/index'
import {MAX_GRAPHEME_LENGTH} from 'lib/constants'
-import {useIsKeyboardVisible} from 'lib/hooks/useIsKeyboardVisible'
import {usePalette} from 'lib/hooks/usePalette'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {cleanError} from 'lib/strings/errors'
import {insertMentionAt} from 'lib/strings/mention-manip'
import {shortenLinks} from 'lib/strings/rich-text-manip'
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 {GalleryModel} from 'state/models/media/gallery'
import {ComposerOpts} from 'state/shell/composer'
@@ -66,6 +65,7 @@ import {UserAvatar} from '../util/UserAvatar'
import {CharProgress} from './char-progress/CharProgress'
import {ExternalEmbed} from './ExternalEmbed'
import {GifAltText} from './GifAltText'
+import {KeyboardAccessory} from './KeyboardAccessory'
import {LabelsBtn} from './labels/LabelsBtn'
import {Gallery} from './photos/Gallery'
import {OpenCameraBtn} from './photos/OpenCameraBtn'
@@ -112,7 +112,6 @@ export const ComposePost = observer(function ComposePost({
const discardPromptControl = Prompt.usePromptControl()
const {closeAllDialogs} = useDialogStateControlContext()
- const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true})
const [isProcessing, setIsProcessing] = useState(false)
const [processingState, setProcessingState] = useState('')
const [error, setError] = useState('')
@@ -150,11 +149,10 @@ export const ComposePost = observer(function ComposePost({
const insets = useSafeAreaInsets()
const viewStyles = useMemo(
() => ({
- paddingBottom:
- isAndroid || (isIOS && !isKeyboardVisible) ? insets.bottom : 0,
+ paddingBottom: isNative ? insets.bottom + 80 : 0,
paddingTop: isMobile && isWeb ? 15 : 0,
}),
- [insets, isKeyboardVisible, isMobile],
+ [insets, isMobile],
)
const onPressCancel = useCallback(() => {
@@ -355,199 +353,202 @@ export const ComposePost = observer(function ComposePost({
)
return (
-
-
-
-
-
- Cancel
-
-
-
- {isProcessing ? (
- <>
- {processingState}
-
-
-
- >
- ) : (
- <>
-
- {replyTo ? null : (
-
- )}
- {canPost ? (
-
-
-
- {replyTo ? (
- Reply
- ) : (
- Post
- )}
-
-
-
- ) : (
-
-
- Post
-
-
- )}
- >
- )}
-
- {requireAltTextEnabled && gallery.needsAltText && (
-
-
-
-
-
- One or more images is missing alt text.
-
-
- )}
- {error !== '' && (
-
-
-
-
- {error}
-
- )}
-
- {replyTo ? : undefined}
-
-
-
-
+
+
+
+
+ msg`Closes post composer and discards post draft`,
+ )}>
+
+ Cancel
+
+
+
+ {isProcessing ? (
+ <>
+ {processingState}
+
+
+
+ >
+ ) : (
+ <>
+
+ {replyTo ? null : (
+
+ )}
+ {canPost ? (
+
+
+
+ {replyTo ? (
+ Reply
+ ) : (
+ Post
+ )}
+
+
+
+ ) : (
+
+
+ Post
+
+
+ )}
+ >
+ )}
-
-
- {gallery.isEmpty && extLink && (
-
- {
- setExtLink(undefined)
- setExtGif(undefined)
- }}
- />
-
+ {requireAltTextEnabled && gallery.needsAltText && (
+
+
+
+
+
+ One or more images is missing alt text.
+
)}
- {quote ? (
-
-
-
+ {error !== '' && (
+
+
+
- {quote.uri !== initQuote?.uri && (
- setQuote(undefined)} />
- )}
+ {error}
- ) : undefined}
-
-
-
-
-
-
-
- {!isMobile ? (
-
- ) : null}
-
-
-
-
+ )}
+
+ {replyTo ? : undefined}
+
+
+
+
+
+
+
+ {gallery.isEmpty && extLink && (
+
+ {
+ setExtLink(undefined)
+ setExtGif(undefined)
+ }}
+ />
+
+
+ )}
+ {quote ? (
+
+
+
+
+ {quote.uri !== initQuote?.uri && (
+ setQuote(undefined)} />
+ )}
+
+ ) : undefined}
+
+
-
+
+
+
+
+
+
+
+ {!isMobile ? (
+
+ ) : null}
+
+
+
+
+
-
+ >
)
})
@@ -639,12 +640,4 @@ const styles = StyleSheet.create({
marginHorizontal: 10,
marginBottom: 4,
},
- bottomBar: {
- flexDirection: 'row',
- paddingVertical: 4,
- paddingLeft: 15,
- paddingRight: 20,
- alignItems: 'center',
- borderTopWidth: 1,
- },
})
diff --git a/src/view/com/composer/KeyboardAccessory.tsx b/src/view/com/composer/KeyboardAccessory.tsx
new file mode 100644
index 0000000000..3eb7cc2721
--- /dev/null
+++ b/src/view/com/composer/KeyboardAccessory.tsx
@@ -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 {children}
+ }
+
+ return (
+
+ {children}
+
+ )
+}