diff --git a/src/state/queries/profile.ts b/src/state/queries/profile.ts
index fad9a1fd73..1bd28d5b1c 100644
--- a/src/state/queries/profile.ts
+++ b/src/state/queries/profile.ts
@@ -3,10 +3,12 @@ import {useQuery, useMutation} from '@tanstack/react-query'
import {useSession} from '../session'
import {updateProfileShadow} from '../cache/profile-shadow'
+export const RQKEY = (did: string) => ['profile', did]
+
export function useProfileQuery({did}: {did: string | undefined}) {
const {agent} = useSession()
return useQuery({
- queryKey: ['profile', did],
+ queryKey: RQKEY(did),
queryFn: async () => {
const res = await agent.getProfile({actor: did || ''})
return res.data
diff --git a/src/view/com/profile/ProfileHeader.tsx b/src/view/com/profile/ProfileHeader.tsx
index eb8ca6cabb..ea3b863013 100644
--- a/src/view/com/profile/ProfileHeader.tsx
+++ b/src/view/com/profile/ProfileHeader.tsx
@@ -31,7 +31,6 @@ import {NativeDropdown, DropdownItem} from '../util/forms/NativeDropdown'
import {Link} from '../util/Link'
import {ProfileHeaderSuggestedFollows} from './ProfileHeaderSuggestedFollows'
import {useStores} from 'state/index'
-import {FollowState} from 'state/models/cache/my-follows'
import {useModalControls} from '#/state/modals'
import {
useProfileFollowMutation,
@@ -59,7 +58,6 @@ import {useSession} from '#/state/session'
interface Props {
profile: AppBskyActorDefs.ProfileViewDetailed
moderation: ProfileModeration
- onRefreshAll: () => void
hideBackButton?: boolean
isProfilePreview?: boolean
}
@@ -67,7 +65,6 @@ interface Props {
export function ProfileHeader({
profile,
moderation,
- onRefreshAll,
hideBackButton = false,
isProfilePreview,
}: Props) {
@@ -103,7 +100,6 @@ export function ProfileHeader({
@@ -113,7 +109,6 @@ export function ProfileHeader({
function ProfileHeaderLoaded({
profile,
moderation,
- onRefreshAll,
hideBackButton = false,
isProfilePreview,
}: Props) {
@@ -203,9 +198,8 @@ function ProfileHeaderLoaded({
openModal({
name: 'edit-profile',
profileView: profile,
- onUpdate: onRefreshAll,
})
- }, [track, openModal, profile, onRefreshAll])
+ }, [track, openModal, profile])
const onPressShare = React.useCallback(() => {
track('ProfileHeader:ShareButtonClicked')
@@ -256,7 +250,6 @@ function ProfileHeaderLoaded({
}
try {
await blockMutation.mutateAsync({did: profile.did})
- onRefreshAll()
Toast.show('Account blocked')
} catch (e: any) {
logger.error('Failed to block account', {error: e})
@@ -264,7 +257,7 @@ function ProfileHeaderLoaded({
}
},
})
- }, [track, blockMutation, profile, openModal, onRefreshAll])
+ }, [track, blockMutation, profile, openModal])
const onPressUnblockAccount = React.useCallback(async () => {
track('ProfileHeader:UnblockAccountButtonClicked')
@@ -282,7 +275,6 @@ function ProfileHeaderLoaded({
did: profile.did,
blockUri: profile.viewer.blocking,
})
- onRefreshAll()
Toast.show('Account unblocked')
} catch (e: any) {
logger.error('Failed to unblock account', {error: e})
@@ -290,7 +282,7 @@ function ProfileHeaderLoaded({
}
},
})
- }, [track, unblockMutation, profile, openModal, onRefreshAll])
+ }, [track, unblockMutation, profile, openModal])
const onPressReportAccount = React.useCallback(() => {
track('ProfileHeader:ReportAccountButtonClicked')
diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx
index 73a4c9d172..dab8988ad5 100644
--- a/src/view/screens/Profile.tsx
+++ b/src/view/screens/Profile.tsx
@@ -1,38 +1,26 @@
-import React, {useEffect, useMemo, useState} from 'react'
+import React, {useMemo} from 'react'
import {ActivityIndicator, StyleSheet, View} from 'react-native'
import {useFocusEffect} from '@react-navigation/native'
import {AppBskyActorDefs, moderateProfile, ModerationOpts} from '@atproto/api'
-import {Trans, msg} from '@lingui/macro'
+import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
-import {ViewSelector, ViewSelectorHandle} from '../com/util/ViewSelector'
+import {ViewSelectorHandle} from '../com/util/ViewSelector'
import {CenteredView} from '../com/util/Views'
import {ScreenHider} from 'view/com/util/moderation/ScreenHider'
-import {ProfileUiModel, Sections} from 'state/models/ui/profile'
import {Feed} from 'view/com/posts/Feed'
import {useStores} from 'state/index'
import {ProfileHeader} from '../com/profile/ProfileHeader'
-import {FeedSlice} from '../com/posts/FeedSlice'
import {PagerWithHeader} from 'view/com/pager/PagerWithHeader'
-import {ListCard} from 'view/com/lists/ListCard'
-import {
- PostFeedLoadingPlaceholder,
- ProfileCardFeedLoadingPlaceholder,
-} from '../com/util/LoadingPlaceholder'
import {ErrorScreen} from '../com/util/error/ErrorScreen'
-import {ErrorMessage} from '../com/util/error/ErrorMessage'
import {EmptyState} from '../com/util/EmptyState'
-import {Text} from '../com/util/text/Text'
import {FAB} from '../com/util/fab/FAB'
import {s, colors} from 'lib/styles'
import {useAnalytics} from 'lib/analytics/analytics'
import {ComposeIcon2} from 'lib/icons'
-import {FeedSourceCard} from 'view/com/feeds/FeedSourceCard'
-import {FeedSourceModel} from 'state/models/content/feed-source'
import {useSetTitle} from 'lib/hooks/useSetTitle'
import {combinedDisplayName} from 'lib/strings/display-names'
-import {logger} from '#/logger'
import {OnScrollHandler} from '#/lib/hooks/useOnMainScroll'
import {FeedDescriptor} from '#/state/queries/post-feed'
import {useResolveDidQuery} from '#/state/queries/resolve-uri'
@@ -53,14 +41,39 @@ export const ProfileScreen = withAuthRequired(function ProfileScreenImpl({
const name =
route.params.name === 'me' ? currentAccount?.did : route.params.name
const moderationOpts = useModerationOpts()
- const {data: resolvedDid, error: resolveError} = useResolveDidQuery(name)
+ const {
+ data: resolvedDid,
+ error: resolveError,
+ refetch: refetchDid,
+ isFetching: isFetchingDid,
+ } = useResolveDidQuery(name)
const {
data: profile,
dataUpdatedAt,
error: profileError,
+ refetch: refetchProfile,
+ isFetching: isFetchingProfile,
} = useProfileQuery({
did: resolvedDid?.did,
})
+
+ const onPressTryAgain = React.useCallback(() => {
+ if (resolveError) {
+ refetchDid()
+ } else {
+ refetchProfile()
+ }
+ }, [resolveError, refetchDid, refetchProfile])
+
+ if (isFetchingDid || isFetchingProfile) {
+ return (
+
+
+
+
+
+ )
+ }
if (resolveError || profileError) {
return (
@@ -68,6 +81,7 @@ export const ProfileScreen = withAuthRequired(function ProfileScreenImpl({
testID="profileErrorScreen"
title="Oops!"
message={cleanError(resolveError || profileError)}
+ onPressTryAgain={onPressTryAgain}
/>
)
@@ -82,11 +96,15 @@ export const ProfileScreen = withAuthRequired(function ProfileScreenImpl({
/>
)
}
+ // should never happen
return (
-
-
-
+
)
})
@@ -112,6 +130,8 @@ function ProfileScreenLoaded({
const viewSelectorRef = React.useRef(null)
const setDrawerSwipeDisabled = useSetDrawerSwipeDisabled()
+ useSetTitle(combinedDisplayName(profile))
+
const moderation = useMemo(
() => moderateProfile(profile, moderationOpts),
[profile, moderationOpts],
@@ -126,11 +146,12 @@ function ProfileScreenLoaded({
useFocusEffect(
React.useCallback(() => {
setMinimalShellMode(false)
+ screen('Profile')
const softResetSub = store.onScreenSoftReset(() => {
viewSelectorRef.current?.scrollToTop()
})
return () => softResetSub.remove()
- }, [store, viewSelectorRef, setMinimalShellMode]),
+ }, [store, viewSelectorRef, setMinimalShellMode, screen]),
)
useFocusEffect(
@@ -155,14 +176,6 @@ function ProfileScreenLoaded({
store.shell.openComposer({mention})
}, [store, currentAccount, track, profile])
- const onRefresh = React.useCallback(() => {
- // TODO
- }, [])
-
- const onPressTryAgain = React.useCallback(() => {
- // TODO
- }, [])
-
const onPageSelected = React.useCallback(
i => {
setCurrentPage(i)
@@ -178,11 +191,10 @@ function ProfileScreenLoaded({
)
- }, [profile, moderation, onRefresh, hideBackButton])
+ }, [profile, moderation, hideBackButton])
return (
(
return (
(
},
)
-function LoadingMoreFooter() {
- return (
-
-
-
- )
-}
-
const styles = StyleSheet.create({
container: {
flexDirection: 'column',