Fix convo header loading state (#7603)

* get initial convo state from cache

* undo useConvoQuery changes

* fix shadowing situation with new hook
This commit is contained in:
Samuel Newman
2025-02-03 14:37:24 -08:00
committed by GitHub
parent fa8607b861
commit 32b28d6662
11 changed files with 174 additions and 84 deletions
-1
View File
@@ -236,7 +236,6 @@ export function MessagesScreen({navigation, route}: Props) {
onEndReachedThreshold={isNative ? 1.5 : 0}
initialNumToRender={initialNumToRender}
windowSize={11}
// @ts-ignore our .web version only -sfn
desktopFixedHeight
sideBorders={false}
/>
+27 -32
View File
@@ -1,6 +1,10 @@
import React, {useCallback} from 'react'
import {View} from 'react-native'
import {AppBskyActorDefs, moderateProfile, ModerationOpts} from '@atproto/api'
import {
AppBskyActorDefs,
moderateProfile,
ModerationDecision,
} from '@atproto/api'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useFocusEffect, useNavigation} from '@react-navigation/native'
@@ -10,7 +14,7 @@ import {useEmail} from '#/lib/hooks/useEmail'
import {useEnableKeyboardControllerScreen} from '#/lib/hooks/useEnableKeyboardController'
import {CommonNavigatorParams, NavigationProp} from '#/lib/routes/types'
import {isWeb} from '#/platform/detection'
import {useProfileShadow} from '#/state/cache/profile-shadow'
import {Shadow, useMaybeProfileShadow} from '#/state/cache/profile-shadow'
import {ConvoProvider, isConvoActive, useConvo} from '#/state/messages/convo'
import {ConvoStatus} from '#/state/messages/convo/types'
import {useCurrentConvoId} from '#/state/messages/current-convo-id'
@@ -72,9 +76,15 @@ function Inner() {
const {_} = useLingui()
const moderationOpts = useModerationOpts()
const {data: recipient} = useProfileQuery({
const {data: recipientUnshadowed} = useProfileQuery({
did: convoState.recipients?.[0].did,
})
const recipient = useMaybeProfileShadow(recipientUnshadowed)
const moderation = React.useMemo(() => {
if (!recipient || !moderationOpts) return null
return moderateProfile(recipient, moderationOpts)
}, [recipient, moderationOpts])
// Because we want to give the list a chance to asynchronously scroll to the end before it is visible to the user,
// we use `hasScrolled` to determine when to render. With that said however, there is a chance that the chat will be
@@ -110,11 +120,16 @@ function Inner() {
return (
<Layout.Center style={[a.flex_1]}>
{!readyToShow && <MessagesListHeader />}
{!readyToShow &&
(moderation ? (
<MessagesListHeader moderation={moderation} profile={recipient} />
) : (
<MessagesListHeader />
))}
<View style={[a.flex_1]}>
{moderationOpts && recipient ? (
{moderation && recipient ? (
<InnerReady
moderationOpts={moderationOpts}
moderation={moderation}
recipient={recipient}
hasScrolled={hasScrolled}
setHasScrolled={setHasScrolled}
@@ -144,38 +159,22 @@ function Inner() {
}
function InnerReady({
moderationOpts,
recipient: recipientUnshadowed,
moderation,
recipient,
hasScrolled,
setHasScrolled,
}: {
moderationOpts: ModerationOpts
recipient: AppBskyActorDefs.ProfileViewBasic
moderation: ModerationDecision
recipient: Shadow<AppBskyActorDefs.ProfileViewBasic>
hasScrolled: boolean
setHasScrolled: React.Dispatch<React.SetStateAction<boolean>>
}) {
const {_} = useLingui()
const convoState = useConvo()
const navigation = useNavigation<NavigationProp>()
const recipient = useProfileShadow(recipientUnshadowed)
const verifyEmailControl = useDialogControl()
const {needsEmailVerification} = useEmail()
const moderation = React.useMemo(() => {
return moderateProfile(recipient, moderationOpts)
}, [recipient, moderationOpts])
const blockInfo = React.useMemo(() => {
const modui = moderation.ui('profileView')
const blocks = modui.alerts.filter(alert => alert.type === 'blocking')
const listBlocks = blocks.filter(alert => alert.source.type === 'list')
const userBlock = blocks.find(alert => alert.source.type === 'user')
return {
listBlocks,
userBlock,
}
}, [moderation])
React.useEffect(() => {
if (needsEmailVerification) {
verifyEmailControl.open()
@@ -184,11 +183,7 @@ function InnerReady({
return (
<>
<MessagesListHeader
profile={recipient}
moderation={moderation}
blockInfo={blockInfo}
/>
<MessagesListHeader profile={recipient} moderation={moderation} />
{isConvoActive(convoState) && (
<MessagesList
hasScrolled={hasScrolled}
@@ -199,7 +194,7 @@ function InnerReady({
recipient={recipient}
convoId={convoState.convo.id}
hasMessages={convoState.items.length > 0}
blockInfo={blockInfo}
moderation={moderation}
/>
}
/>
@@ -9,6 +9,7 @@ import {
} from '@atproto/api'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useQueryClient} from '@tanstack/react-query'
import {GestureActionView} from '#/lib/custom-animations/GestureActionView'
import {useHaptics} from '#/lib/haptics'
@@ -23,7 +24,11 @@ import {
import {isNative} from '#/platform/detection'
import {useProfileShadow} from '#/state/cache/profile-shadow'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {useMarkAsReadMutation} from '#/state/queries/messages/conversation'
import {
precacheConvoQuery,
useMarkAsReadMutation,
} from '#/state/queries/messages/conversation'
import {precacheProfile} from '#/state/queries/profile'
import {useSession} from '#/state/session'
import {TimeElapsed} from '#/view/com/util/TimeElapsed'
import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar'
@@ -89,6 +94,7 @@ function ChatListItemReady({
[profile, moderationOpts],
)
const playHaptic = useHaptics()
const queryClient = useQueryClient()
const isUnread = convo.unreadCount > 0
const blockInfo = useMemo(() => {
@@ -198,6 +204,8 @@ function ChatListItemReady({
const onPress = useCallback(
(e: GestureResponderEvent) => {
precacheProfile(queryClient, profile)
precacheConvoQuery(queryClient, convo)
decrementBadgeCount(convo.unreadCount)
if (isDeletedAccount) {
e.preventDefault()
@@ -207,7 +215,7 @@ function ChatListItemReady({
logEvent('chat:open', {logContext: 'ChatsList'})
}
},
[convo.unreadCount, isDeletedAccount, menuControl],
[isDeletedAccount, menuControl, queryClient, profile, convo],
)
const onLongPress = useCallback(() => {