This commit is contained in:
Hailey
2024-05-30 09:13:16 -07:00
parent 175627b1e0
commit 48c26b8c75
3 changed files with 206 additions and 203 deletions
@@ -1,31 +0,0 @@
import React from 'react'
import {useKeyboardHandler} from 'react-native-keyboard-controller'
import Animated, {
useAnimatedStyle,
useSharedValue,
} from 'react-native-reanimated'
export function KeyboardPadding({maxHeight}: {maxHeight?: number}) {
const keyboardHeight = useSharedValue(0)
useKeyboardHandler(
{
onMove: e => {
'worklet'
if (maxHeight && e.height > maxHeight) {
keyboardHeight.value = maxHeight
} else {
keyboardHeight.value = e.height
}
},
},
[maxHeight],
)
const animatedStyle = useAnimatedStyle(() => ({
height: keyboardHeight.value,
}))
return <Animated.View style={animatedStyle} />
}
+39 -2
View File
@@ -1,3 +1,40 @@
export function KeyboardPadding({maxHeight: _}: {maxHeight?: number}) { import React from 'react'
return null import {useKeyboardHandler} from 'react-native-keyboard-controller'
import Animated, {
useAnimatedStyle,
useSharedValue,
} from 'react-native-reanimated'
import {isAndroid} from 'platform/detection'
export function KeyboardPadding({androidOnly = true}: {androidOnly?: boolean}) {
if (!isAndroid && androidOnly) {
return null
}
return <KeyboardPaddingInner />
}
function KeyboardPaddingInner({maxHeight}: {maxHeight?: number}) {
const keyboardHeight = useSharedValue(0)
useKeyboardHandler(
{
onMove: e => {
'worklet'
if (maxHeight && e.height > maxHeight) {
keyboardHeight.value = maxHeight
} else {
keyboardHeight.value = e.height
}
},
},
[maxHeight],
)
const animatedStyle = useAnimatedStyle(() => ({
height: keyboardHeight.value,
}))
return <Animated.View style={animatedStyle} />
} }
+167 -170
View File
@@ -13,10 +13,7 @@ import {
TouchableOpacity, TouchableOpacity,
View, View,
} from 'react-native' } from 'react-native'
import { import {KeyboardStickyView} from 'react-native-keyboard-controller'
KeyboardAvoidingView,
KeyboardStickyView,
} from 'react-native-keyboard-controller'
import Animated, { import Animated, {
interpolateColor, interpolateColor,
useAnimatedStyle, useAnimatedStyle,
@@ -70,6 +67,7 @@ import {ComposerReplyTo} from 'view/com/composer/ComposerReplyTo'
import {atoms as a, useTheme} from '#/alf' import {atoms as a, useTheme} from '#/alf'
import {Button} from '#/components/Button' import {Button} from '#/components/Button'
import {EmojiArc_Stroke2_Corner0_Rounded as EmojiSmile} from '#/components/icons/Emoji' import {EmojiArc_Stroke2_Corner0_Rounded as EmojiSmile} from '#/components/icons/Emoji'
import {KeyboardPadding} from '#/components/KeyboardPadding'
import * as Prompt from '#/components/Prompt' import * as Prompt from '#/components/Prompt'
import {QuoteEmbed, QuoteX} from '../util/post-embeds/QuoteEmbed' import {QuoteEmbed, QuoteX} from '../util/post-embeds/QuoteEmbed'
import {Text} from '../util/text/Text' import {Text} from '../util/text/Text'
@@ -401,175 +399,174 @@ export const ComposePost = observer(function ComposePost({
return ( return (
<> <>
<KeyboardAvoidingView <View
testID="composePostView" style={[s.flex1, viewStyles]}
behavior="padding" aria-modal
style={s.flex1} accessibilityViewIsModal
keyboardVerticalOffset={replyTo ? 60 : isAndroid ? 120 : 100}> testID="composePostView">
<View style={[s.flex1, viewStyles]} aria-modal accessibilityViewIsModal> <Animated.View
<Animated.View style={[
style={[ styles.topbar,
styles.topbar, topBarAnimatedStyle,
topBarAnimatedStyle, isWeb && isTabletOrDesktop && styles.topbarDesktop,
isWeb && isTabletOrDesktop && styles.topbarDesktop, ]}>
]}> <TouchableOpacity
<TouchableOpacity testID="composerDiscardButton"
testID="composerDiscardButton" onPress={onPressCancel}
onPress={onPressCancel} onAccessibilityEscape={onPressCancel}
onAccessibilityEscape={onPressCancel} accessibilityRole="button"
accessibilityRole="button" accessibilityLabel={_(msg`Cancel`)}
accessibilityLabel={_(msg`Cancel`)} accessibilityHint={_(
accessibilityHint={_( msg`Closes post composer and discards post draft`,
msg`Closes post composer and discards post draft`, )}
)} hitSlop={HITSLOP_10}>
hitSlop={HITSLOP_10}> <Text style={[pal.link, s.f18]}>
<Text style={[pal.link, s.f18]}> <Trans>Cancel</Trans>
<Trans>Cancel</Trans> </Text>
</Text> </TouchableOpacity>
</TouchableOpacity> <View style={s.flex1} />
<View style={s.flex1} /> {isProcessing ? (
{isProcessing ? ( <>
<> <Text style={pal.textLight}>{processingState}</Text>
<Text style={pal.textLight}>{processingState}</Text> <View style={styles.postBtn}>
<View style={styles.postBtn}> <ActivityIndicator />
<ActivityIndicator /> </View>
</View> </>
</> ) : (
) : ( <>
<> <LabelsBtn
<LabelsBtn labels={labels}
labels={labels} onChange={setLabels}
onChange={setLabels} hasMedia={hasMedia}
hasMedia={hasMedia} />
/> {canPost ? (
{canPost ? ( <TouchableOpacity
<TouchableOpacity testID="composerPublishBtn"
testID="composerPublishBtn" onPress={onPressPublish}
onPress={onPressPublish} accessibilityRole="button"
accessibilityRole="button" accessibilityLabel={
accessibilityLabel={ replyTo ? _(msg`Publish reply`) : _(msg`Publish post`)
replyTo ? _(msg`Publish reply`) : _(msg`Publish post`) }
} accessibilityHint="">
accessibilityHint=""> <LinearGradient
<LinearGradient colors={[
colors={[ gradients.blueLight.start,
gradients.blueLight.start, gradients.blueLight.end,
gradients.blueLight.end, ]}
]} start={{x: 0, y: 0}}
start={{x: 0, y: 0}} end={{x: 1, y: 1}}
end={{x: 1, y: 1}} style={styles.postBtn}>
style={styles.postBtn}> <Text style={[s.white, s.f16, s.bold]}>
<Text style={[s.white, s.f16, s.bold]}> {replyTo ? (
{replyTo ? ( <Trans context="action">Reply</Trans>
<Trans context="action">Reply</Trans> ) : (
) : ( <Trans context="action">Post</Trans>
<Trans context="action">Post</Trans> )}
)}
</Text>
</LinearGradient>
</TouchableOpacity>
) : (
<View style={[styles.postBtn, pal.btn]}>
<Text style={[pal.textLight, s.f16, s.bold]}>
<Trans context="action">Post</Trans>
</Text> </Text>
</View> </LinearGradient>
)} </TouchableOpacity>
</> ) : (
)} <View style={[styles.postBtn, pal.btn]}>
</Animated.View> <Text style={[pal.textLight, s.f16, s.bold]}>
{isAltTextRequiredAndMissing && ( <Trans context="action">Post</Trans>
<View style={[styles.reminderLine, pal.viewLight]}> </Text>
<View style={styles.errorIcon}>
<FontAwesomeIcon
icon="exclamation"
style={{color: colors.red4}}
size={10}
/>
</View>
<Text style={[pal.text, s.flex1]}>
<Trans>One or more images is missing alt text.</Trans>
</Text>
</View>
)}
{error !== '' && (
<View style={styles.errorLine}>
<View style={styles.errorIcon}>
<FontAwesomeIcon
icon="exclamation"
style={{color: colors.red4}}
size={10}
/>
</View>
<Text style={[s.red4, s.flex1]}>{error}</Text>
</View>
)}
<Animated.ScrollView
onScroll={scrollHandler}
style={styles.scrollView}
keyboardShouldPersistTaps="always">
{replyTo ? <ComposerReplyTo replyTo={replyTo} /> : undefined}
<View
style={[
styles.textInputLayout,
isNative && styles.textInputLayoutMobile,
]}>
<UserAvatar
avatar={currentProfile?.avatar}
size={50}
type={currentProfile?.associated?.labeler ? 'labeler' : 'user'}
/>
<TextInput
ref={textInput}
richtext={richtext}
placeholder={selectTextInputPlaceholder}
autoFocus={true}
setRichText={setRichText}
onPhotoPasted={onPhotoPasted}
onPressPublish={onPressPublish}
onNewLink={onNewLink}
onError={setError}
accessible={true}
accessibilityLabel={_(msg`Write post`)}
accessibilityHint={_(
msg`Compose posts up to ${MAX_GRAPHEME_LENGTH} characters in length`,
)}
/>
</View>
<Gallery gallery={gallery} />
{gallery.isEmpty && extLink && (
<View style={a.relative}>
<ExternalEmbed
link={extLink}
gif={extGif}
onRemove={() => {
setExtLink(undefined)
setExtGif(undefined)
}}
/>
<GifAltText
link={extLink}
gif={extGif}
onSubmit={handleChangeGifAltText}
/>
</View>
)}
{quote ? (
<View style={[s.mt5, isWeb && s.mb10]}>
<View style={{pointerEvents: 'none'}}>
<QuoteEmbed quote={quote} />
</View> </View>
{quote.uri !== initQuote?.uri && ( )}
<QuoteX onRemove={() => setQuote(undefined)} /> </>
)} )}
</Animated.View>
{isAltTextRequiredAndMissing && (
<View style={[styles.reminderLine, pal.viewLight]}>
<View style={styles.errorIcon}>
<FontAwesomeIcon
icon="exclamation"
style={{color: colors.red4}}
size={10}
/>
</View>
<Text style={[pal.text, s.flex1]}>
<Trans>One or more images is missing alt text.</Trans>
</Text>
</View>
)}
{error !== '' && (
<View style={styles.errorLine}>
<View style={styles.errorIcon}>
<FontAwesomeIcon
icon="exclamation"
style={{color: colors.red4}}
size={10}
/>
</View>
<Text style={[s.red4, s.flex1]}>{error}</Text>
</View>
)}
<Animated.ScrollView
onScroll={scrollHandler}
style={styles.scrollView}
keyboardShouldPersistTaps="always">
{replyTo ? <ComposerReplyTo replyTo={replyTo} /> : undefined}
<View
style={[
styles.textInputLayout,
isNative && styles.textInputLayoutMobile,
]}>
<UserAvatar
avatar={currentProfile?.avatar}
size={50}
type={currentProfile?.associated?.labeler ? 'labeler' : 'user'}
/>
<TextInput
ref={textInput}
richtext={richtext}
placeholder={selectTextInputPlaceholder}
autoFocus={true}
setRichText={setRichText}
onPhotoPasted={onPhotoPasted}
onPressPublish={onPressPublish}
onNewLink={onNewLink}
onError={setError}
accessible={true}
accessibilityLabel={_(msg`Write post`)}
accessibilityHint={_(
msg`Compose posts up to ${MAX_GRAPHEME_LENGTH} characters in length`,
)}
/>
</View>
<Gallery gallery={gallery} />
{gallery.isEmpty && extLink && (
<View style={a.relative}>
<ExternalEmbed
link={extLink}
gif={extGif}
onRemove={() => {
setExtLink(undefined)
setExtGif(undefined)
}}
/>
<GifAltText
link={extLink}
gif={extGif}
onSubmit={handleChangeGifAltText}
/>
</View>
)}
{quote ? (
<View style={[s.mt5, isWeb && s.mb10]}>
<View style={{pointerEvents: 'none'}}>
<QuoteEmbed quote={quote} />
</View> </View>
) : undefined} {quote.uri !== initQuote?.uri && (
</Animated.ScrollView> <QuoteX onRemove={() => setQuote(undefined)} />
<SuggestedLanguage text={richtext.text} /> )}
</View> </View>
</KeyboardAvoidingView> ) : undefined}
</Animated.ScrollView>
<SuggestedLanguage text={richtext.text} />
<KeyboardPadding androidOnly={false} />
</View>
<KeyboardStickyView <KeyboardStickyView
offset={{closed: isIOS ? -insets.bottom : 0, opened: 0}}> offset={{closed: isIOS ? -insets.bottom : 0, opened: 0}}>
{replyTo ? null : ( {replyTo ? null : (