From e45f0b6c43b751a3b23f8967fee4c6664a6844ae Mon Sep 17 00:00:00 2001 From: Hailey <153161762+haileyok@users.noreply.github.com> Date: Tue, 30 Jan 2024 15:48:03 -0800 Subject: [PATCH] Autofocus the alt text input on all platforms, improve dismissability on native (#2690) * sneak in a eslint fix * autofocus the alt text input whenever we open the modal * properly use the hook --- src/state/modals/index.tsx | 2 +- src/view/com/modals/AltImage.tsx | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/state/modals/index.tsx b/src/state/modals/index.tsx index 45856e10..ab710a3d 100644 --- a/src/state/modals/index.tsx +++ b/src/state/modals/index.tsx @@ -6,7 +6,7 @@ import {Image as RNImage} from 'react-native-image-crop-picker' import {ImageModel} from '#/state/models/media/image' import {GalleryModel} from '#/state/models/media/gallery' import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' -import {EmbedPlayerSource} from '#/lib/strings/embed-player.ts' +import {EmbedPlayerSource} from '#/lib/strings/embed-player' import {ThreadgateSetting} from '../queries/threadgate' export interface ConfirmModal { diff --git a/src/view/com/modals/AltImage.tsx b/src/view/com/modals/AltImage.tsx index 5156511d..7671c29c 100644 --- a/src/view/com/modals/AltImage.tsx +++ b/src/view/com/modals/AltImage.tsx @@ -4,7 +4,9 @@ import { StyleSheet, TouchableOpacity, View, + TextInput as RNTextInput, useWindowDimensions, + ScrollView as RNScrollView, } from 'react-native' import {ScrollView, TextInput} from './util' import {Image} from 'expo-image' @@ -13,6 +15,7 @@ import {gradients, s} from 'lib/styles' import {enforceLen} from 'lib/strings/helpers' import {MAX_ALT_TEXT} from 'lib/constants' import {useTheme} from 'lib/ThemeContext' +import {useIsKeyboardVisible} from 'lib/hooks/useIsKeyboardVisible' import {Text} from '../util/text/Text' import LinearGradient from 'react-native-linear-gradient' import {isWeb} from 'platform/detection' @@ -34,6 +37,24 @@ export function Component({image}: Props) { const [altText, setAltText] = useState(image.altText) const windim = useWindowDimensions() const {closeModal} = useModalControls() + const inputRef = React.useRef(null) + const scrollViewRef = React.useRef(null) + const keyboardShown = useIsKeyboardVisible() + + // Autofocus hack when we open the modal. We have to wait for the animation to complete first + React.useEffect(() => { + setTimeout(() => { + inputRef.current?.focus() + }, 500) + }, []) + + // We'd rather be at the bottom here so that we can easily dismiss the modal instead of having to scroll + // (especially on android, it acts weird) + React.useEffect(() => { + if (keyboardShown[0]) { + scrollViewRef.current?.scrollToEnd() + } + }, [keyboardShown]) const imageStyles = useMemo(() => { const maxWidth = isWeb ? 450 : windim.width @@ -71,6 +92,7 @@ export function Component({image}: Props) { testID="altTextImageModal" style={[pal.view, styles.scrollContainer]} keyboardShouldPersistTaps="always" + ref={scrollViewRef} nativeID="imageAltText"> @@ -97,7 +119,8 @@ export function Component({image}: Props) { accessibilityLabel={_(msg`Image alt text`)} accessibilityHint="" accessibilityLabelledBy="imageAltText" - autoFocus + // @ts-ignore This is fine, type is weird on the BottomSheetTextInput + ref={inputRef} />