add simple fallback implmentation
This commit is contained in:
@@ -74,6 +74,9 @@ a[role='link'][data-no-underline='1']:hover {
|
|||||||
height: 0;
|
height: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
.composer-fallback-input::placeholder {
|
||||||
|
color: #8d8e96;
|
||||||
|
}
|
||||||
.ProseMirror .mention {
|
.ProseMirror .mention {
|
||||||
color: #0085ff;
|
color: #0085ff;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,24 @@
|
|||||||
import {lazy, Suspense, useEffect, useState} from 'react'
|
import {
|
||||||
|
lazy,
|
||||||
|
Suspense,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useImperativeHandle,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from 'react'
|
||||||
import {StyleSheet, View} from 'react-native'
|
import {StyleSheet, View} from 'react-native'
|
||||||
import Animated, {FadeIn, FadeOut} from 'react-native-reanimated'
|
import Animated, {FadeIn, FadeOut} from 'react-native-reanimated'
|
||||||
|
import {RichText} from '@atproto/api'
|
||||||
import {Trans} from '@lingui/macro'
|
import {Trans} from '@lingui/macro'
|
||||||
|
|
||||||
import {textInputWebEmitter} from '#/view/com/composer/text-input/textInputWebEmitter'
|
import {textInputWebEmitter} from '#/view/com/composer/text-input/textInputWebEmitter'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useAlf, useTheme} from '#/alf'
|
||||||
|
import {normalizeTextStyles} from '#/alf/typography'
|
||||||
import {Portal} from '#/components/Portal'
|
import {Portal} from '#/components/Portal'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {type TextInputProps} from './TextInput.types'
|
import {type TextInputProps, type TextInputRef} from './TextInput.types'
|
||||||
import {getImageOrVideoFromUri} from './web/uri-to-media'
|
import {getImageOrVideoFromUri} from './web/uri-to-media'
|
||||||
|
|
||||||
const RichTextInput = lazy(async () => {
|
const RichTextInput = lazy(async () => {
|
||||||
@@ -16,6 +27,101 @@ const RichTextInput = lazy(async () => {
|
|||||||
return await import('./web/RichTextInputWeb')
|
return await import('./web/RichTextInputWeb')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function FallbackTextInput({
|
||||||
|
ref,
|
||||||
|
richtext,
|
||||||
|
placeholder,
|
||||||
|
webForceMinHeight,
|
||||||
|
setRichText,
|
||||||
|
onFocus,
|
||||||
|
}: Pick<
|
||||||
|
TextInputProps,
|
||||||
|
| 'ref'
|
||||||
|
| 'richtext'
|
||||||
|
| 'placeholder'
|
||||||
|
| 'webForceMinHeight'
|
||||||
|
| 'setRichText'
|
||||||
|
| 'onFocus'
|
||||||
|
>) {
|
||||||
|
const {theme: t, fonts} = useAlf()
|
||||||
|
const textareaRef = useRef<HTMLTextAreaElement>(null)
|
||||||
|
|
||||||
|
const handleChange = useCallback(
|
||||||
|
(e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
|
const newText = e.target.value
|
||||||
|
const newRt = new RichText({text: newText})
|
||||||
|
newRt.detectFacetsWithoutResolution()
|
||||||
|
setRichText(newRt)
|
||||||
|
},
|
||||||
|
[setRichText],
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
|
||||||
|
if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {
|
||||||
|
textInputWebEmitter.emit('publish')
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useImperativeHandle(
|
||||||
|
ref,
|
||||||
|
(): TextInputRef => ({
|
||||||
|
focus: () => textareaRef.current?.focus(),
|
||||||
|
blur: () => textareaRef.current?.blur(),
|
||||||
|
getCursorPosition: () => undefined,
|
||||||
|
maybeClosePopup: () => false,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Move cursor to end after autofocus
|
||||||
|
const textarea = textareaRef.current
|
||||||
|
if (textarea) {
|
||||||
|
const len = textarea.value.length
|
||||||
|
textarea.setSelectionRange(len, len)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const inputStyle = useMemo((): React.CSSProperties => {
|
||||||
|
const style = normalizeTextStyles(
|
||||||
|
[a.text_lg, a.leading_snug, t.atoms.text],
|
||||||
|
{
|
||||||
|
fontScale: fonts.scaleMultiplier,
|
||||||
|
fontFamily: fonts.family,
|
||||||
|
flags: {},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
style.lineHeight = style.lineHeight
|
||||||
|
? ((style.lineHeight + 'px') as unknown as number)
|
||||||
|
: undefined
|
||||||
|
style.minHeight = webForceMinHeight ? 140 : undefined
|
||||||
|
return {
|
||||||
|
...style,
|
||||||
|
width: '100%',
|
||||||
|
border: 'none',
|
||||||
|
outline: 'none',
|
||||||
|
resize: 'none',
|
||||||
|
background: 'transparent',
|
||||||
|
padding: 0,
|
||||||
|
margin: 0,
|
||||||
|
} as React.CSSProperties
|
||||||
|
}, [t, fonts, webForceMinHeight])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<textarea
|
||||||
|
ref={textareaRef}
|
||||||
|
className="composer-fallback-input"
|
||||||
|
autoFocus
|
||||||
|
value={richtext.text}
|
||||||
|
onChange={handleChange}
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
|
onFocus={onFocus}
|
||||||
|
placeholder={placeholder}
|
||||||
|
style={inputStyle}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export function TextInput(props: TextInputProps) {
|
export function TextInput(props: TextInputProps) {
|
||||||
const {hasRightPadding, isActive, onPhotoPasted, onPressPublish} = props
|
const {hasRightPadding, isActive, onPhotoPasted, onPressPublish} = props
|
||||||
|
|
||||||
@@ -90,7 +196,7 @@ export function TextInput(props: TextInputProps) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<View style={[styles.container, hasRightPadding && styles.rightPadding]}>
|
<View style={[styles.container, hasRightPadding && styles.rightPadding]}>
|
||||||
<Suspense fallback={<View style={styles.fallback} />}>
|
<Suspense fallback={<FallbackTextInput {...props} />}>
|
||||||
<RichTextInput {...props} />
|
<RichTextInput {...props} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</View>
|
</View>
|
||||||
@@ -163,7 +269,4 @@ const styles = StyleSheet.create({
|
|||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
},
|
},
|
||||||
fallback: {
|
|
||||||
minHeight: 140,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user