diff options
-rw-r--r-- | src/screens/Messages/components/MessageInput.tsx | 48 | ||||
-rw-r--r-- | src/view/screens/Storybook/Forms.tsx | 19 | ||||
-rw-r--r-- | src/view/screens/Storybook/index.tsx | 32 |
3 files changed, 59 insertions, 40 deletions
diff --git a/src/screens/Messages/components/MessageInput.tsx b/src/screens/Messages/components/MessageInput.tsx index 85509211b..c97918fa0 100644 --- a/src/screens/Messages/components/MessageInput.tsx +++ b/src/screens/Messages/components/MessageInput.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import {useCallback, useState} from 'react' import {Pressable, TextInput, useWindowDimensions, View} from 'react-native' import { useFocusedInputHandler, @@ -19,7 +19,7 @@ import Graphemer from 'graphemer' import {HITSLOP_10, MAX_DM_GRAPHEME_LENGTH} from '#/lib/constants' import {useHaptics} from '#/lib/haptics' import {useEmail} from '#/lib/hooks/useEmail' -import {isIOS} from '#/platform/detection' +import {isIOS, isWeb} from '#/platform/detection' import { useMessageDraft, useSaveMessageDraft, @@ -58,16 +58,17 @@ export function MessageInput({ const isInputScrollable = useSharedValue(false) const inputStyles = useSharedInputStyles() - const [isFocused, setIsFocused] = React.useState(false) - const [message, setMessage] = React.useState(getDraft) + const [isFocused, setIsFocused] = useState(false) + const [message, setMessage] = useState(getDraft) const inputRef = useAnimatedRef<TextInput>() + const [shouldEnforceClear, setShouldEnforceClear] = useState(false) const {needsEmailVerification} = useEmail() useSaveMessageDraft(message) useExtractEmbedFromFacets(message, setEmbed) - const onSubmit = React.useCallback(() => { + const onSubmit = useCallback(() => { if (needsEmailVerification) { return } @@ -81,14 +82,18 @@ export function MessageInput({ clearDraft() onSendMessage(message) playHaptic() - setMessage('') setEmbed(undefined) - - // Pressing the send button causes the text input to lose focus, so we need to - // re-focus it after sending - setTimeout(() => { - inputRef.current?.focus() - }, 100) + setMessage('') + if (isIOS) { + setShouldEnforceClear(true) + } + if (isWeb) { + // Pressing the send button causes the text input to lose focus, so we need to + // re-focus it after sending + setTimeout(() => { + inputRef.current?.focus() + }, 100) + } }, [ needsEmailVerification, hasEmbed, @@ -97,8 +102,8 @@ export function MessageInput({ onSendMessage, playHaptic, setEmbed, - _, inputRef, + _, ]) useFocusedInputHandler( @@ -149,8 +154,21 @@ export function MessageInput({ placeholder={_(msg`Write a message`)} placeholderTextColor={t.palette.contrast_500} value={message} + onChange={evt => { + // bit of a hack: iOS automatically accepts autocomplete suggestions when you tap anywhere on the screen + // including the button we just pressed - and this overrides clearing the input! so we watch for the + // next change and double make sure the input is cleared. It should *always* send an onChange event after + // clearing via setMessage('') that happens in onSubmit() + // -sfn + if (isIOS && shouldEnforceClear) { + setShouldEnforceClear(false) + setMessage('') + return + } + const text = evt.nativeEvent.text + setMessage(text) + }} multiline={true} - onChangeText={setMessage} style={[ a.flex_1, a.text_md, @@ -160,7 +178,7 @@ export function MessageInput({ animatedStyle, ]} keyboardAppearance={t.name === 'light' ? 'light' : 'dark'} - blurOnSubmit={false} + submitBehavior="submit" onFocus={() => setIsFocused(true)} onBlur={() => setIsFocused(false)} ref={inputRef} diff --git a/src/view/screens/Storybook/Forms.tsx b/src/view/screens/Storybook/Forms.tsx index 8ec118ae3..ad130b376 100644 --- a/src/view/screens/Storybook/Forms.tsx +++ b/src/view/screens/Storybook/Forms.tsx @@ -1,5 +1,5 @@ import React from 'react' -import {View} from 'react-native' +import {TextInput, View} from 'react-native' import {atoms as a} from '#/alf' import {Button, ButtonText} from '#/components/Button' @@ -19,6 +19,8 @@ export function Forms() { const [value, setValue] = React.useState('') const [date, setDate] = React.useState('2001-01-01') + const inputRef = React.useRef<TextInput>(null) + return ( <View style={[a.gap_4xl, a.align_start]}> <H1>Forms</H1> @@ -33,22 +35,23 @@ export function Forms() { /> <View style={[a.flex_row, a.align_start, a.gap_sm]}> - <View - style={[ - { - width: '50%', - }, - ]}> + <View style={[a.flex_1]}> <TextField.Root> <TextField.Icon icon={Globe} /> <TextField.Input + inputRef={inputRef} value={value} onChangeText={setValue} label="Text field" /> </TextField.Root> </View> - <Button label="Submit" size="large" variant="solid" color="primary"> + <Button + label="Submit" + size="large" + variant="solid" + color="primary" + onPress={() => inputRef.current?.clear()}> <ButtonText>Submit</ButtonText> </Button> </View> diff --git a/src/view/screens/Storybook/index.tsx b/src/view/screens/Storybook/index.tsx index de3d46533..0146bc3c6 100644 --- a/src/view/screens/Storybook/index.tsx +++ b/src/view/screens/Storybook/index.tsx @@ -1,13 +1,11 @@ import React from 'react' -import {ScrollView, View} from 'react-native' +import {View} from 'react-native' import {useNavigation} from '@react-navigation/native' import {NavigationProp} from '#/lib/routes/types' -import {isWeb} from '#/platform/detection' import {useSetThemePrefs} from '#/state/shell' -import {CenteredView} from '#/view/com/util/Views' import {ListContained} from '#/view/screens/Storybook/ListContained' -import {atoms as a, ThemeProvider, useTheme} from '#/alf' +import {atoms as a, ThemeProvider} from '#/alf' import {Button, ButtonText} from '#/components/Button' import * as Layout from '#/components/Layout' import {Admonitions} from './Admonitions' @@ -27,25 +25,27 @@ import {Typography} from './Typography' export function Storybook() { return ( <Layout.Screen> - {isWeb ? ( + <Layout.Header.Outer> + <Layout.Header.BackButton /> + <Layout.Header.Content> + <Layout.Header.TitleText>Storybook</Layout.Header.TitleText> + </Layout.Header.Content> + <Layout.Header.Slot /> + </Layout.Header.Outer> + <Layout.Content keyboardShouldPersistTaps="handled"> <StorybookInner /> - ) : ( - <ScrollView> - <StorybookInner /> - </ScrollView> - )} + </Layout.Content> </Layout.Screen> ) } function StorybookInner() { - const t = useTheme() const {setColorMode, setDarkTheme} = useSetThemePrefs() const [showContainedList, setShowContainedList] = React.useState(false) const navigation = useNavigation<NavigationProp>() return ( - <CenteredView style={[t.atoms.bg]}> + <> <View style={[a.p_xl, a.gap_5xl, {paddingBottom: 100}]}> {!showContainedList ? ( <> @@ -100,10 +100,6 @@ function StorybookInner() { <ButtonText>Open Shared Prefs Tester</ButtonText> </Button> - <Admonitions /> - - <Settings /> - <ThemeProvider theme="light"> <Theming /> </ThemeProvider> @@ -126,6 +122,8 @@ function StorybookInner() { <Menus /> <Breakpoints /> <Dialogs /> + <Admonitions /> + <Settings /> <Button variant="solid" @@ -150,6 +148,6 @@ function StorybookInner() { </> )} </View> - </CenteredView> + </> ) } |