use RNKC for composer keyboard avoiding view
This commit is contained in:
@@ -1969,18 +1969,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"src/view/com/composer/Composer.tsx": {
|
"src/view/com/composer/Composer.tsx": {
|
||||||
"@typescript-eslint/no-explicit-any": {
|
|
||||||
"count": 2
|
|
||||||
},
|
|
||||||
"@typescript-eslint/no-floating-promises": {
|
|
||||||
"count": 1
|
|
||||||
},
|
|
||||||
"@typescript-eslint/no-misused-promises": {
|
|
||||||
"count": 4
|
|
||||||
},
|
|
||||||
"@typescript-eslint/no-unsafe-member-access": {
|
|
||||||
"count": 2
|
|
||||||
},
|
|
||||||
"react-hooks/immutability": {
|
"react-hooks/immutability": {
|
||||||
"count": 2
|
"count": 2
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import {
|
|||||||
ActivityIndicator,
|
ActivityIndicator,
|
||||||
BackHandler,
|
BackHandler,
|
||||||
Keyboard,
|
Keyboard,
|
||||||
KeyboardAvoidingView,
|
|
||||||
type LayoutChangeEvent,
|
type LayoutChangeEvent,
|
||||||
ScrollView,
|
ScrollView,
|
||||||
type StyleProp,
|
type StyleProp,
|
||||||
@@ -21,6 +20,7 @@ import {
|
|||||||
View,
|
View,
|
||||||
type ViewStyle,
|
type ViewStyle,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
|
import {KeyboardAvoidingView} from 'react-native-keyboard-controller'
|
||||||
// @ts-expect-error no type definition
|
// @ts-expect-error no type definition
|
||||||
import ProgressCircle from 'react-native-progress/Circle'
|
import ProgressCircle from 'react-native-progress/Circle'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
@@ -71,7 +71,6 @@ import {
|
|||||||
SUPPORTED_MIME_TYPES,
|
SUPPORTED_MIME_TYPES,
|
||||||
type SupportedMimeTypes,
|
type SupportedMimeTypes,
|
||||||
} from '#/lib/constants'
|
} from '#/lib/constants'
|
||||||
import {useIsKeyboardVisible} from '#/lib/hooks/useIsKeyboardVisible'
|
|
||||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||||
import {createVideoTelemetry} from '#/lib/media/video/telemetry'
|
import {createVideoTelemetry} from '#/lib/media/video/telemetry'
|
||||||
import {mimeToExt} from '#/lib/media/video/util'
|
import {mimeToExt} from '#/lib/media/video/util'
|
||||||
@@ -286,7 +285,6 @@ export const ComposePost = ({
|
|||||||
const {data: preferences} = usePreferencesQuery()
|
const {data: preferences} = usePreferencesQuery()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
|
|
||||||
const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true})
|
|
||||||
const [isPublishing, setIsPublishing] = useState(false)
|
const [isPublishing, setIsPublishing] = useState(false)
|
||||||
const [publishingStage, setPublishingStage] = useState('')
|
const [publishingStage, setPublishingStage] = useState('')
|
||||||
const [error, setError] = useState('')
|
const [error, setError] = useState('')
|
||||||
@@ -641,7 +639,7 @@ export const ComposePost = ({
|
|||||||
// This is async but we don't await - videos process in the background
|
// This is async but we don't await - videos process in the background
|
||||||
for (const [postIndex, videoInfo] of restoredVideos) {
|
for (const [postIndex, videoInfo] of restoredVideos) {
|
||||||
const postId = posts[postIndex].id
|
const postId = posts[postIndex].id
|
||||||
restoreVideo(postId, videoInfo)
|
void restoreVideo(postId, videoInfo)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[composerDispatch, restoreVideo, ax],
|
[composerDispatch, restoreVideo, ax],
|
||||||
@@ -798,17 +796,9 @@ export const ComposePost = ({
|
|||||||
const viewStyles = useMemo(
|
const viewStyles = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
paddingTop: IS_ANDROID ? insets.top : 0,
|
paddingTop: IS_ANDROID ? insets.top : 0,
|
||||||
paddingBottom:
|
paddingBottom: insets.bottom,
|
||||||
// iOS - when keyboard is closed, keep the bottom bar in the safe area
|
|
||||||
(IS_IOS && !isKeyboardVisible) ||
|
|
||||||
// Android - Android >=35 KeyboardAvoidingView adds double padding when
|
|
||||||
// keyboard is closed, so we subtract that in the offset and add it back
|
|
||||||
// here when the keyboard is open
|
|
||||||
(IS_ANDROID && isKeyboardVisible)
|
|
||||||
? insets.bottom
|
|
||||||
: 0,
|
|
||||||
}),
|
}),
|
||||||
[insets, isKeyboardVisible],
|
[insets.top, insets.bottom],
|
||||||
)
|
)
|
||||||
|
|
||||||
const onPressCancel = useCallback(() => {
|
const onPressCancel = useCallback(() => {
|
||||||
@@ -1042,13 +1032,13 @@ export const ComposePost = ({
|
|||||||
posts,
|
posts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (waitErr: any) {
|
} catch (waitErr) {
|
||||||
logger.info(`composer: waiting for app view failed`, {
|
logger.info(`composer: waiting for app view failed`, {
|
||||||
safeMessage: waitErr,
|
safeMessage: waitErr,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e) {
|
||||||
logger.error(e, {
|
logger.error(e instanceof Error ? e : String(e), {
|
||||||
message: `Composer: create post failed`,
|
message: `Composer: create post failed`,
|
||||||
hasImages: filteredThread.posts.some(
|
hasImages: filteredThread.posts.some(
|
||||||
p =>
|
p =>
|
||||||
@@ -1057,7 +1047,7 @@ export const ComposePost = ({
|
|||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
let err = cleanError(e.message)
|
let err = e instanceof Error ? cleanError(e.message) : String(e)
|
||||||
if (
|
if (
|
||||||
e instanceof apilib.ReplyDeletedError ||
|
e instanceof apilib.ReplyDeletedError ||
|
||||||
err.includes('not locate record')
|
err.includes('not locate record')
|
||||||
@@ -1359,8 +1349,8 @@ export const ComposePost = ({
|
|||||||
publishingStage={publishingStage}
|
publishingStage={publishingStage}
|
||||||
topBarAnimatedStyle={topBarAnimatedStyle}
|
topBarAnimatedStyle={topBarAnimatedStyle}
|
||||||
onCancel={onPressCancel}
|
onCancel={onPressCancel}
|
||||||
onPublish={onPressPublish}
|
onPublish={() => void onPressPublish()}
|
||||||
onSelectDraft={handleSelectDraft}
|
onSelectDraft={draft => void handleSelectDraft(draft)}
|
||||||
onSaveDraft={saveCurrentDraft}
|
onSaveDraft={saveCurrentDraft}
|
||||||
onDiscard={handleClearComposer}
|
onDiscard={handleClearComposer}
|
||||||
isEmpty={isComposerEmpty}
|
isEmpty={isComposerEmpty}
|
||||||
@@ -1473,7 +1463,7 @@ export const ComposePost = ({
|
|||||||
{allPostsWithinLimit && (
|
{allPostsWithinLimit && (
|
||||||
<Prompt.Action
|
<Prompt.Action
|
||||||
cta={composerState.draftId ? l`Save changes` : l`Save draft`}
|
cta={composerState.draftId ? l`Save changes` : l`Save draft`}
|
||||||
onPress={handleSaveDraft}
|
onPress={() => void handleSaveDraft()}
|
||||||
color="primary"
|
color="primary"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -1633,7 +1623,7 @@ let ComposerPost = memo(function ComposerPost({
|
|||||||
postId: post.id,
|
postId: post.id,
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
onPhotoPasted={onPhotoPasted}
|
onPhotoPasted={uri => void onPhotoPasted(uri)}
|
||||||
onNewLink={onNewLink}
|
onNewLink={onNewLink}
|
||||||
onError={onError}
|
onError={onError}
|
||||||
onPressPublish={onPublish}
|
onPressPublish={onPublish}
|
||||||
@@ -2124,7 +2114,7 @@ function ComposerFooter({
|
|||||||
}),
|
}),
|
||||||
).catch(e => {
|
).catch(e => {
|
||||||
logger.error(`createComposerImage failed`, {
|
logger.error(`createComposerImage failed`, {
|
||||||
safeMessage: e.message,
|
safeMessage: e instanceof Error ? e.message : String(e),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -2361,24 +2351,31 @@ function useScrollTracker({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function useKeyboardVerticalOffset() {
|
function useKeyboardVerticalOffset() {
|
||||||
const {top, bottom} = useSafeAreaInsets()
|
const insets = useSafeAreaInsets()
|
||||||
|
|
||||||
// Android etc
|
// the keyboardavoidingview has bottom padding to avoid being obscured by the safe area when keyboard is closed.
|
||||||
if (!IS_IOS) {
|
// however, this leads to a gap when the keyboard is open. we account for that by subtracting the bottom inset when open.
|
||||||
// need to account for the edge-to-edge nav bar
|
let keyboardVerticalOffset = insets.bottom * -1
|
||||||
return bottom * -1
|
|
||||||
|
// iOS requires a bit of extra offset to account for the native sheet not being at the top of the screen
|
||||||
|
if (IS_IOS) {
|
||||||
|
// they ditched the gap behaviour on 26
|
||||||
|
if (IS_LIQUID_GLASS) {
|
||||||
|
keyboardVerticalOffset += insets.top
|
||||||
|
}
|
||||||
|
|
||||||
|
// iPhone SE
|
||||||
|
else if (insets.top === 20) {
|
||||||
|
keyboardVerticalOffset += 40
|
||||||
|
}
|
||||||
|
|
||||||
|
// all other iPhones on <26
|
||||||
|
else {
|
||||||
|
keyboardVerticalOffset += insets.top + 10
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// they ditched the gap behaviour on 26
|
return keyboardVerticalOffset
|
||||||
if (IS_LIQUID_GLASS) {
|
|
||||||
return top
|
|
||||||
}
|
|
||||||
|
|
||||||
// iPhone SE
|
|
||||||
if (top === 20) return 40
|
|
||||||
|
|
||||||
// all other iPhones on <26
|
|
||||||
return top + 10
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function whenAppViewReady(
|
async function whenAppViewReady(
|
||||||
|
|||||||
Reference in New Issue
Block a user