Composer UI fixes (#6065)

* Fix close button overlap

* Make footer actually sticky on web

* Special toast for thread

* Only stick to bottom for last post
This commit is contained in:
dan
2024-11-01 22:02:39 +00:00
committed by GitHub
parent 46004fb2d0
commit 3eb531b000
3 changed files with 29 additions and 7 deletions
+20 -5
View File
@@ -443,7 +443,9 @@ export const ComposePost = ({
} }
onClose() onClose()
Toast.show( Toast.show(
replyTo thread.posts.length > 1
? _(msg`Your posts have been published`)
: replyTo
? _(msg`Your reply has been published`) ? _(msg`Your reply has been published`)
: _(msg`Your post has been published`), : _(msg`Your post has been published`),
) )
@@ -523,6 +525,7 @@ export const ComposePost = ({
} }
}, [composerState]) }, [composerState])
const isLastThreadedPost = thread.posts.length > 1 && nextPost === undefined
const { const {
scrollHandler, scrollHandler,
onScrollViewContentSizeChange, onScrollViewContentSizeChange,
@@ -531,7 +534,7 @@ export const ComposePost = ({
bottomBarAnimatedStyle, bottomBarAnimatedStyle,
} = useScrollTracker({ } = useScrollTracker({
scrollViewRef, scrollViewRef,
stickyBottom: true, stickyBottom: isLastThreadedPost,
}) })
const keyboardVerticalOffset = useKeyboardVerticalOffset() const keyboardVerticalOffset = useKeyboardVerticalOffset()
@@ -564,7 +567,7 @@ export const ComposePost = ({
</> </>
) )
const isFooterSticky = !isNative && thread.posts.length > 1 const isWebFooterSticky = !isNative && thread.posts.length > 1
return ( return (
<BottomSheetPortalProvider> <BottomSheetPortalProvider>
<KeyboardAvoidingView <KeyboardAvoidingView
@@ -615,6 +618,7 @@ export const ComposePost = ({
dispatch={composerDispatch} dispatch={composerDispatch}
textInput={post.id === activePost.id ? textInput : null} textInput={post.id === activePost.id ? textInput : null}
isFirstPost={index === 0} isFirstPost={index === 0}
isPartOfThread={thread.posts.length > 1}
isReply={index > 0 || !!replyTo} isReply={index > 0 || !!replyTo}
isActive={post.id === activePost.id} isActive={post.id === activePost.id}
canRemovePost={thread.posts.length > 1} canRemovePost={thread.posts.length > 1}
@@ -624,11 +628,13 @@ export const ComposePost = ({
onPublish={onComposerPostPublish} onPublish={onComposerPostPublish}
onError={setError} onError={setError}
/> />
{isFooterSticky && post.id === activePost.id && footer} {isWebFooterSticky && post.id === activePost.id && (
<View style={styles.stickyFooterWeb}>{footer}</View>
)}
</React.Fragment> </React.Fragment>
))} ))}
</Animated.ScrollView> </Animated.ScrollView>
{!isFooterSticky && footer} {!isWebFooterSticky && footer}
</View> </View>
<Prompt.Basic <Prompt.Basic
@@ -651,6 +657,7 @@ let ComposerPost = React.memo(function ComposerPost({
isActive, isActive,
isReply, isReply,
isFirstPost, isFirstPost,
isPartOfThread,
canRemovePost, canRemovePost,
canRemoveQuote, canRemoveQuote,
onClearVideo, onClearVideo,
@@ -664,6 +671,7 @@ let ComposerPost = React.memo(function ComposerPost({
isActive: boolean isActive: boolean
isReply: boolean isReply: boolean
isFirstPost: boolean isFirstPost: boolean
isPartOfThread: boolean
canRemovePost: boolean canRemovePost: boolean
canRemoveQuote: boolean canRemoveQuote: boolean
onClearVideo: (postId: string) => void onClearVideo: (postId: string) => void
@@ -743,6 +751,8 @@ let ComposerPost = React.memo(function ComposerPost({
placeholder={selectTextInputPlaceholder} placeholder={selectTextInputPlaceholder}
autoFocus autoFocus
webForceMinHeight={forceMinHeight} webForceMinHeight={forceMinHeight}
// To avoid overlap with the close button:
hasRightPadding={isPartOfThread}
isActive={isActive} isActive={isActive}
setRichText={rt => { setRichText={rt => {
dispatchPost({type: 'update_richtext', richtext: rt}) dispatchPost({type: 'update_richtext', richtext: rt})
@@ -1395,6 +1405,11 @@ const styles = StyleSheet.create({
paddingVertical: 6, paddingVertical: 6,
marginLeft: 12, marginLeft: 12,
}, },
stickyFooterWeb: {
// @ts-ignore web-only
position: 'sticky',
bottom: 0,
},
errorLine: { errorLine: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
@@ -44,6 +44,7 @@ interface TextInputProps extends ComponentProps<typeof RNTextInput> {
richtext: RichText richtext: RichText
placeholder: string placeholder: string
webForceMinHeight: boolean webForceMinHeight: boolean
hasRightPadding: boolean
isActive: boolean isActive: boolean
setRichText: (v: RichText) => void setRichText: (v: RichText) => void
onPhotoPasted: (uri: string) => void onPhotoPasted: (uri: string) => void
@@ -61,6 +62,7 @@ export const TextInput = forwardRef(function TextInputImpl(
{ {
richtext, richtext,
placeholder, placeholder,
hasRightPadding,
setRichText, setRichText,
onPhotoPasted, onPhotoPasted,
onNewLink, onNewLink,
@@ -232,7 +234,7 @@ export const TextInput = forwardRef(function TextInputImpl(
}, [t, richtext, inputTextStyle]) }, [t, richtext, inputTextStyle])
return ( return (
<View style={[a.flex_1, a.pl_md]}> <View style={[a.flex_1, a.pl_md, hasRightPadding && a.pr_4xl]}>
<PasteInput <PasteInput
testID="composerTextInput" testID="composerTextInput"
ref={textInput} ref={textInput}
@@ -42,6 +42,7 @@ interface TextInputProps {
placeholder: string placeholder: string
suggestedLinks: Set<string> suggestedLinks: Set<string>
webForceMinHeight: boolean webForceMinHeight: boolean
hasRightPadding: boolean
isActive: boolean isActive: boolean
setRichText: (v: RichText | ((v: RichText) => RichText)) => void setRichText: (v: RichText | ((v: RichText) => RichText)) => void
onPhotoPasted: (uri: string) => void onPhotoPasted: (uri: string) => void
@@ -56,6 +57,7 @@ export const TextInput = React.forwardRef(function TextInputImpl(
richtext, richtext,
placeholder, placeholder,
webForceMinHeight, webForceMinHeight,
hasRightPadding,
isActive, isActive,
setRichText, setRichText,
onPhotoPasted, onPhotoPasted,
@@ -307,7 +309,7 @@ export const TextInput = React.forwardRef(function TextInputImpl(
return ( return (
<> <>
<View style={styles.container}> <View style={[styles.container, hasRightPadding && styles.rightPadding]}>
{/* @ts-ignore inputStyle is fine */} {/* @ts-ignore inputStyle is fine */}
<EditorContent editor={editor} style={inputStyle} /> <EditorContent editor={editor} style={inputStyle} />
</View> </View>
@@ -373,6 +375,9 @@ const styles = StyleSheet.create({
marginLeft: 8, marginLeft: 8,
marginBottom: 10, marginBottom: 10,
}, },
rightPadding: {
paddingRight: 32,
},
dropContainer: { dropContainer: {
backgroundColor: '#0007', backgroundColor: '#0007',
pointerEvents: 'none', pointerEvents: 'none',