Some nits
This commit is contained in:
@@ -48,7 +48,7 @@ import {
|
|||||||
import {AutosizedTextarea} from '#/components/forms/AutosizedTextarea'
|
import {AutosizedTextarea} from '#/components/forms/AutosizedTextarea'
|
||||||
import {useOnKeyboard} from '#/components/hooks/useOnKeyboard'
|
import {useOnKeyboard} from '#/components/hooks/useOnKeyboard'
|
||||||
import {Span, Text} from '#/components/Typography'
|
import {Span, Text} from '#/components/Typography'
|
||||||
import {IS_WEB, IS_WEB_TOUCH_DEVICE} from '#/env'
|
import {IS_IOS, IS_WEB, IS_WEB_TOUCH_DEVICE} from '#/env'
|
||||||
|
|
||||||
export type SubmitRequest =
|
export type SubmitRequest =
|
||||||
| {
|
| {
|
||||||
@@ -219,11 +219,27 @@ export function Composer({
|
|||||||
transform: [{translateY: -inputScrollSharedValue.value}],
|
transform: [{translateY: -inputScrollSharedValue.value}],
|
||||||
}))
|
}))
|
||||||
const textStyle = useMemo(() => {
|
const textStyle = useMemo(() => {
|
||||||
return normalizeTextStyles([a.leading_snug, rawTextStyle, t.atoms.text], {
|
const ts = normalizeTextStyles(
|
||||||
fontScale: fonts.scaleMultiplier,
|
[a.leading_snug, rawTextStyle, t.atoms.text],
|
||||||
fontFamily: fonts.family,
|
{
|
||||||
flags: {},
|
fontScale: fonts.scaleMultiplier,
|
||||||
})
|
fontFamily: fonts.family,
|
||||||
|
flags: {},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* On iOS, having a lineHeight on the Text component causes the text to be
|
||||||
|
* vertically misaligned with the TextInput.
|
||||||
|
*
|
||||||
|
* This only seems to be an issue on iOS, and not on Android or web. It's
|
||||||
|
* possible that this is a bug in React Native's Text component on iOS,
|
||||||
|
* but in the meantime, we'll just remove the lineHeight on iOS to ensure
|
||||||
|
* the text is properly aligned.
|
||||||
|
*/
|
||||||
|
if (IS_IOS) {
|
||||||
|
delete ts.lineHeight
|
||||||
|
}
|
||||||
|
return ts
|
||||||
}, [rawTextStyle, fonts])
|
}, [rawTextStyle, fonts])
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {useCallback, useEffect, useMemo, useRef, useState} from 'react'
|
import {useEffect, useMemo, useRef, useState} from 'react'
|
||||||
import {
|
import {
|
||||||
TextInput,
|
TextInput,
|
||||||
type TextInputContentSizeChangeEvent,
|
type TextInputContentSizeChangeEvent,
|
||||||
@@ -19,7 +19,6 @@ export function AutosizedTextarea({
|
|||||||
|
|
||||||
onChangeText: onChangeTextOuter,
|
onChangeText: onChangeTextOuter,
|
||||||
onContentSizeChange: onContentSizeChangeOuter,
|
onContentSizeChange: onContentSizeChangeOuter,
|
||||||
|
|
||||||
style,
|
style,
|
||||||
...rest
|
...rest
|
||||||
}: Omit<TextInputProps, 'multiline'> & {
|
}: Omit<TextInputProps, 'multiline'> & {
|
||||||
@@ -33,11 +32,14 @@ export function AutosizedTextarea({
|
|||||||
const {theme: t, fonts} = useAlf()
|
const {theme: t, fonts} = useAlf()
|
||||||
const {processedStyle, minHeight, maxHeight} = useMemo(() => {
|
const {processedStyle, minHeight, maxHeight} = useMemo(() => {
|
||||||
const fs = flatten(style)
|
const fs = flatten(style)
|
||||||
const ts = normalizeTextStyles([a.leading_snug, fs, t.atoms.text], {
|
const ts = normalizeTextStyles(
|
||||||
fontScale: fonts.scaleMultiplier,
|
[a.text_md, a.leading_snug, t.atoms.text, fs],
|
||||||
fontFamily: fonts.family,
|
{
|
||||||
flags: {},
|
fontScale: fonts.scaleMultiplier,
|
||||||
})
|
fontFamily: fonts.family,
|
||||||
|
flags: {},
|
||||||
|
},
|
||||||
|
)
|
||||||
const lineHeight = ts.lineHeight || 20
|
const lineHeight = ts.lineHeight || 20
|
||||||
const padding = extractPadding(fs ?? {})
|
const padding = extractPadding(fs ?? {})
|
||||||
const verticalSpace = padding.paddingTop + padding.paddingBottom
|
const verticalSpace = padding.paddingTop + padding.paddingBottom
|
||||||
@@ -50,15 +52,11 @@ export function AutosizedTextarea({
|
|||||||
* On iOS, minHeight/maxHeight works fine natively.
|
* On iOS, minHeight/maxHeight works fine natively.
|
||||||
*/
|
*/
|
||||||
const tas = IS_WEB
|
const tas = IS_WEB
|
||||||
? {height: lineHeight + verticalSpace}
|
? {height: mh}
|
||||||
: IS_ANDROID
|
: IS_ANDROID
|
||||||
? {height: mh}
|
? {height: mh}
|
||||||
: {minHeight: mh, maxHeight: xh}
|
: {minHeight: mh, maxHeight: xh}
|
||||||
|
|
||||||
if (IS_IOS) {
|
|
||||||
delete ts.lineHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
processedStyle: {
|
processedStyle: {
|
||||||
...ts,
|
...ts,
|
||||||
@@ -78,52 +76,46 @@ export function AutosizedTextarea({
|
|||||||
const [androidInputHeight, setAndroidInputHeight] = useState(minHeight)
|
const [androidInputHeight, setAndroidInputHeight] = useState(minHeight)
|
||||||
|
|
||||||
const prevHeight = useRef(0)
|
const prevHeight = useRef(0)
|
||||||
const onChangeText = useCallback(
|
const onChangeText = (text: string) => {
|
||||||
(text: string) => {
|
if (IS_WEB) {
|
||||||
if (IS_WEB) {
|
const el = textInputRef.current as unknown as HTMLTextAreaElement
|
||||||
const el = textInputRef.current as unknown as HTMLTextAreaElement
|
if (el) {
|
||||||
if (el) {
|
el.style.height = '0px'
|
||||||
el.style.height = '0px'
|
const scrollHeight = el.scrollHeight
|
||||||
const scrollHeight = el.scrollHeight
|
const nextHeight = Math.min(
|
||||||
const nextHeight = Math.min(
|
Math.max(scrollHeight, minHeight),
|
||||||
Math.max(scrollHeight, minHeight),
|
maxHeight,
|
||||||
maxHeight,
|
)
|
||||||
)
|
el.style.height = `${nextHeight}px`
|
||||||
el.style.height = `${nextHeight}px`
|
el.style.overflowY = scrollHeight > maxHeight ? 'auto' : 'hidden'
|
||||||
el.style.overflowY = scrollHeight > maxHeight ? 'auto' : 'hidden'
|
if (nextHeight !== prevHeight.current) {
|
||||||
if (nextHeight !== prevHeight.current) {
|
prevHeight.current = nextHeight
|
||||||
prevHeight.current = nextHeight
|
onUpdateHeight?.(nextHeight)
|
||||||
onUpdateHeight?.(nextHeight)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (IS_IOS) {
|
|
||||||
textInputRef.current?.measure((_x, _y, _w, h) => {
|
|
||||||
if (h !== prevHeight.current) {
|
|
||||||
prevHeight.current = h
|
|
||||||
onUpdateHeight?.(h)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onChangeTextOuter?.(text)
|
|
||||||
},
|
|
||||||
[onChangeTextOuter, minHeight, maxHeight, onUpdateHeight],
|
|
||||||
)
|
|
||||||
|
|
||||||
const onContentSizeChange = useCallback(
|
|
||||||
(e: TextInputContentSizeChangeEvent) => {
|
|
||||||
if (IS_ANDROID) {
|
|
||||||
const h = Math.ceil(e.nativeEvent.contentSize.height)
|
|
||||||
const nextHeight = Math.min(Math.max(h, minHeight), maxHeight)
|
|
||||||
if (nextHeight !== androidInputHeight) {
|
|
||||||
setAndroidInputHeight(nextHeight)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (IS_IOS) {
|
||||||
|
textInputRef.current?.measure((_x, _y, _w, h) => {
|
||||||
|
if (h !== prevHeight.current) {
|
||||||
|
prevHeight.current = h
|
||||||
|
onUpdateHeight?.(h)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
onContentSizeChangeOuter?.(e)
|
onChangeTextOuter?.(text)
|
||||||
},
|
}
|
||||||
[onContentSizeChangeOuter, minHeight, maxHeight, androidInputHeight],
|
|
||||||
)
|
const onContentSizeChange = (e: TextInputContentSizeChangeEvent) => {
|
||||||
|
if (IS_ANDROID) {
|
||||||
|
const h = Math.ceil(e.nativeEvent.contentSize.height)
|
||||||
|
const nextHeight = Math.min(Math.max(h, minHeight), maxHeight)
|
||||||
|
if (nextHeight !== androidInputHeight) {
|
||||||
|
setAndroidInputHeight(nextHeight)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onContentSizeChangeOuter?.(e)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On Android, height is driven by onContentSizeChange (see the TextInput
|
* On Android, height is driven by onContentSizeChange (see the TextInput
|
||||||
|
|||||||
Reference in New Issue
Block a user