clean up logic for showing request buttons (#7964)
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import React, {useCallback, useRef} from 'react'
|
import {useCallback, useEffect, useRef, useState} from 'react'
|
||||||
import {LayoutChangeEvent, View} from 'react-native'
|
import {LayoutChangeEvent, View} from 'react-native'
|
||||||
import {useKeyboardHandler} from 'react-native-keyboard-controller'
|
import {useKeyboardHandler} from 'react-native-keyboard-controller'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
@@ -25,8 +25,12 @@ import {
|
|||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isNative} from '#/platform/detection'
|
import {isNative} from '#/platform/detection'
|
||||||
import {isWeb} from '#/platform/detection'
|
import {isWeb} from '#/platform/detection'
|
||||||
import {isConvoActive, useConvoActive} from '#/state/messages/convo'
|
import {
|
||||||
import {ConvoItem, ConvoStatus} from '#/state/messages/convo/types'
|
ActiveConvoStates,
|
||||||
|
isConvoActive,
|
||||||
|
useConvoActive,
|
||||||
|
} from '#/state/messages/convo'
|
||||||
|
import {ConvoItem, ConvoState, ConvoStatus} from '#/state/messages/convo/types'
|
||||||
import {useGetPost} from '#/state/queries/post'
|
import {useGetPost} from '#/state/queries/post'
|
||||||
import {useAgent} from '#/state/session'
|
import {useAgent} from '#/state/session'
|
||||||
import {useShellLayout} from '#/state/shell/shell-layout'
|
import {useShellLayout} from '#/state/shell/shell-layout'
|
||||||
@@ -100,16 +104,15 @@ export function MessagesList({
|
|||||||
|
|
||||||
const flatListRef = useAnimatedRef<ListMethods>()
|
const flatListRef = useAnimatedRef<ListMethods>()
|
||||||
|
|
||||||
const [newMessagesPill, setNewMessagesPill] = React.useState({
|
const [newMessagesPill, setNewMessagesPill] = useState({
|
||||||
show: false,
|
show: false,
|
||||||
startContentOffset: 0,
|
startContentOffset: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
const [emojiPickerState, setEmojiPickerState] =
|
const [emojiPickerState, setEmojiPickerState] = useState<EmojiPickerState>({
|
||||||
React.useState<EmojiPickerState>({
|
isOpen: false,
|
||||||
isOpen: false,
|
pos: {top: 0, left: 0, right: 0, bottom: 0, nextFocusRef: null},
|
||||||
pos: {top: 0, left: 0, right: 0, bottom: 0, nextFocusRef: null},
|
})
|
||||||
})
|
|
||||||
|
|
||||||
// We need to keep track of when the scroll offset is at the bottom of the list to know when to scroll as new items
|
// We need to keep track of when the scroll offset is at the bottom of the list to know when to scroll as new items
|
||||||
// are added to the list. For example, if the user is scrolled up to 1iew older messages, we don't want to scroll to
|
// are added to the list. For example, if the user is scrolled up to 1iew older messages, we don't want to scroll to
|
||||||
@@ -126,8 +129,8 @@ export function MessagesList({
|
|||||||
|
|
||||||
// -- Keep track of background state and positioning for new pill
|
// -- Keep track of background state and positioning for new pill
|
||||||
const layoutHeight = useSharedValue(0)
|
const layoutHeight = useSharedValue(0)
|
||||||
const didBackground = React.useRef(false)
|
const didBackground = useRef(false)
|
||||||
React.useEffect(() => {
|
useEffect(() => {
|
||||||
if (convoState.status === ConvoStatus.Backgrounded) {
|
if (convoState.status === ConvoStatus.Backgrounded) {
|
||||||
didBackground.current = true
|
didBackground.current = true
|
||||||
}
|
}
|
||||||
@@ -218,7 +221,7 @@ export function MessagesList({
|
|||||||
}
|
}
|
||||||
}, [convoState, hasScrolled, layoutHeight])
|
}, [convoState, hasScrolled, layoutHeight])
|
||||||
|
|
||||||
const onScroll = React.useCallback(
|
const onScroll = useCallback(
|
||||||
(e: ReanimatedScrollEvent) => {
|
(e: ReanimatedScrollEvent) => {
|
||||||
'worklet'
|
'worklet'
|
||||||
layoutHeight.set(e.layoutMeasurement.height)
|
layoutHeight.set(e.layoutMeasurement.height)
|
||||||
@@ -376,7 +379,7 @@ export function MessagesList({
|
|||||||
)
|
)
|
||||||
|
|
||||||
// -- List layout changes (opening emoji keyboard, etc.)
|
// -- List layout changes (opening emoji keyboard, etc.)
|
||||||
const onListLayout = React.useCallback(
|
const onListLayout = useCallback(
|
||||||
(e: LayoutChangeEvent) => {
|
(e: LayoutChangeEvent) => {
|
||||||
layoutHeight.set(e.nativeEvent.layout.height)
|
layoutHeight.set(e.nativeEvent.layout.height)
|
||||||
|
|
||||||
@@ -395,13 +398,17 @@ export function MessagesList({
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
const scrollToEndOnPress = React.useCallback(() => {
|
const scrollToEndOnPress = useCallback(() => {
|
||||||
flatListRef.current?.scrollToOffset({
|
flatListRef.current?.scrollToOffset({
|
||||||
offset: prevContentHeight.current,
|
offset: prevContentHeight.current,
|
||||||
animated: true,
|
animated: true,
|
||||||
})
|
})
|
||||||
}, [flatListRef])
|
}, [flatListRef])
|
||||||
|
|
||||||
|
const onOpenEmojiPicker = useCallback((pos: any) => {
|
||||||
|
setEmojiPickerState({isOpen: true, pos})
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* Custom scroll provider so that we can use the `onScroll` event in our custom List implementation */}
|
{/* Custom scroll provider so that we can use the `onScroll` event in our custom List implementation */}
|
||||||
@@ -440,41 +447,17 @@ export function MessagesList({
|
|||||||
) : blocked ? (
|
) : blocked ? (
|
||||||
footer
|
footer
|
||||||
) : (
|
) : (
|
||||||
isConvoActive(convoState) &&
|
<ConversationFooter
|
||||||
!convoState.isFetchingHistory && (
|
convoState={convoState}
|
||||||
<>
|
hasAcceptOverride={hasAcceptOverride}>
|
||||||
{convoState.items.length === 0 ? (
|
<MessageInput
|
||||||
<>
|
onSendMessage={onSendMessage}
|
||||||
<ChatEmptyPill />
|
hasEmbed={!!embedUri}
|
||||||
<MessageInput
|
setEmbed={setEmbed}
|
||||||
onSendMessage={onSendMessage}
|
openEmojiPicker={onOpenEmojiPicker}>
|
||||||
hasEmbed={!!embedUri}
|
<MessageInputEmbed embedUri={embedUri} setEmbed={setEmbed} />
|
||||||
setEmbed={setEmbed}
|
</MessageInput>
|
||||||
openEmojiPicker={pos =>
|
</ConversationFooter>
|
||||||
setEmojiPickerState({isOpen: true, pos})
|
|
||||||
}>
|
|
||||||
<MessageInputEmbed
|
|
||||||
embedUri={embedUri}
|
|
||||||
setEmbed={setEmbed}
|
|
||||||
/>
|
|
||||||
</MessageInput>
|
|
||||||
</>
|
|
||||||
) : convoState.convo.status === 'request' &&
|
|
||||||
!hasAcceptOverride ? (
|
|
||||||
<ChatStatusInfo convoState={convoState} />
|
|
||||||
) : (
|
|
||||||
<MessageInput
|
|
||||||
onSendMessage={onSendMessage}
|
|
||||||
hasEmbed={!!embedUri}
|
|
||||||
setEmbed={setEmbed}
|
|
||||||
openEmojiPicker={pos =>
|
|
||||||
setEmojiPickerState({isOpen: true, pos})
|
|
||||||
}>
|
|
||||||
<MessageInputEmbed embedUri={embedUri} setEmbed={setEmbed} />
|
|
||||||
</MessageInput>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
)}
|
)}
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
|
|
||||||
@@ -490,3 +473,56 @@ export function MessagesList({
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FooterState = 'loading' | 'new-chat' | 'request' | 'standard'
|
||||||
|
|
||||||
|
function getFooterState(
|
||||||
|
convoState: ActiveConvoStates,
|
||||||
|
hasAcceptOverride?: boolean,
|
||||||
|
): FooterState {
|
||||||
|
if (convoState.items.length === 0) {
|
||||||
|
if (convoState.isFetchingHistory) {
|
||||||
|
return 'loading'
|
||||||
|
} else {
|
||||||
|
return 'new-chat'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (convoState.convo.status === 'request' && !hasAcceptOverride) {
|
||||||
|
return 'request'
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'standard'
|
||||||
|
}
|
||||||
|
|
||||||
|
function ConversationFooter({
|
||||||
|
convoState,
|
||||||
|
hasAcceptOverride,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
convoState: ConvoState
|
||||||
|
hasAcceptOverride?: boolean
|
||||||
|
children?: React.ReactNode // message input
|
||||||
|
}) {
|
||||||
|
if (!isConvoActive(convoState)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const footerState = getFooterState(convoState, hasAcceptOverride)
|
||||||
|
|
||||||
|
switch (footerState) {
|
||||||
|
case 'loading':
|
||||||
|
return null
|
||||||
|
case 'new-chat':
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ChatEmptyPill />
|
||||||
|
{children}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
case 'request':
|
||||||
|
return <ChatStatusInfo convoState={convoState} />
|
||||||
|
case 'standard':
|
||||||
|
return children
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user