about summary refs log tree commit diff
path: root/src/components/StarterPack/ProfileStarterPacks.tsx
diff options
context:
space:
mode:
authorSamuel Newman <mozzius@protonmail.com>2025-02-24 11:50:52 -0800
committerGitHub <noreply@github.com>2025-02-24 11:50:52 -0800
commitf9392d4a9688c1ea1bff962c857ff4ae543e46fe (patch)
treed84b3adc155c03e7519c0277a0e6a32366a76ea6 /src/components/StarterPack/ProfileStarterPacks.tsx
parentbdcddee7a568519073939e434f9e3973497b304c (diff)
downloadvoidsky-f9392d4a9688c1ea1bff962c857ff4ae543e46fe.tar.zst
Fix optimistic rendering of profile page (#7830)
* don't hold up rendering on starter packs

* add tab based on profile.associated

* move query into component, fix pending states
Diffstat (limited to 'src/components/StarterPack/ProfileStarterPacks.tsx')
-rw-r--r--src/components/StarterPack/ProfileStarterPacks.tsx57
1 files changed, 28 insertions, 29 deletions
diff --git a/src/components/StarterPack/ProfileStarterPacks.tsx b/src/components/StarterPack/ProfileStarterPacks.tsx
index d8925684b..da5f0dc6a 100644
--- a/src/components/StarterPack/ProfileStarterPacks.tsx
+++ b/src/components/StarterPack/ProfileStarterPacks.tsx
@@ -1,4 +1,9 @@
-import React from 'react'
+import React, {
+  useCallback,
+  useEffect,
+  useImperativeHandle,
+  useState,
+} from 'react'
 import {
   findNodeHandle,
   ListRenderItemInfo,
@@ -6,11 +11,10 @@ import {
   View,
   ViewStyle,
 } from 'react-native'
-import {AppBskyGraphDefs, AppBskyGraphGetActorStarterPacks} from '@atproto/api'
+import {AppBskyGraphDefs} from '@atproto/api'
 import {msg, Trans} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 import {useNavigation} from '@react-navigation/native'
-import {InfiniteData, UseInfiniteQueryResult} from '@tanstack/react-query'
 
 import {useGenerateStarterPackMutation} from '#/lib/generate-starterpack'
 import {useBottomBarOffset} from '#/lib/hooks/useBottomBarOffset'
@@ -19,28 +23,27 @@ import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
 import {NavigationProp} from '#/lib/routes/types'
 import {parseStarterPackUri} from '#/lib/strings/starter-pack'
 import {logger} from '#/logger'
+import {useActorStarterPacksQuery} from '#/state/queries/actor-starter-packs'
 import {List, ListRef} from '#/view/com/util/List'
-import {Text} from '#/view/com/util/text/Text'
+import {FeedLoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
 import {atoms as a, ios, useTheme} from '#/alf'
 import {Button, ButtonIcon, ButtonText} from '#/components/Button'
 import {useDialogControl} from '#/components/Dialog'
+import {VerifyEmailDialog} from '#/components/dialogs/VerifyEmailDialog'
+import {PlusSmall_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus'
 import {LinearGradientBackground} from '#/components/LinearGradientBackground'
 import {Loader} from '#/components/Loader'
 import * as Prompt from '#/components/Prompt'
 import {Default as StarterPackCard} from '#/components/StarterPack/StarterPackCard'
-import {VerifyEmailDialog} from '../dialogs/VerifyEmailDialog'
-import {PlusSmall_Stroke2_Corner0_Rounded as Plus} from '../icons/Plus'
+import {Text} from '#/components/Typography'
 
 interface SectionRef {
   scrollToTop: () => void
 }
 
 interface ProfileFeedgensProps {
-  starterPacksQuery: UseInfiniteQueryResult<
-    InfiniteData<AppBskyGraphGetActorStarterPacks.OutputSchema, unknown>,
-    Error
-  >
   scrollElRef: ListRef
+  did: string
   headerOffset: number
   enabled?: boolean
   style?: StyleProp<ViewStyle>
@@ -58,8 +61,8 @@ export const ProfileStarterPacks = React.forwardRef<
   ProfileFeedgensProps
 >(function ProfileFeedgensImpl(
   {
-    starterPacksQuery: query,
     scrollElRef,
+    did,
     headerOffset,
     enabled,
     style,
@@ -71,17 +74,18 @@ export const ProfileStarterPacks = React.forwardRef<
 ) {
   const t = useTheme()
   const bottomBarOffset = useBottomBarOffset(100)
-  const [isPTRing, setIsPTRing] = React.useState(false)
-  const {data, refetch, isFetching, hasNextPage, fetchNextPage} = query
+  const [isPTRing, setIsPTRing] = useState(false)
+  const {data, refetch, isFetching, hasNextPage, fetchNextPage} =
+    useActorStarterPacksQuery({did, enabled})
   const {isTabletOrDesktop} = useWebMediaQueries()
 
   const items = data?.pages.flatMap(page => page.starterPacks)
 
-  React.useImperativeHandle(ref, () => ({
+  useImperativeHandle(ref, () => ({
     scrollToTop: () => {},
   }))
 
-  const onRefresh = React.useCallback(async () => {
+  const onRefresh = useCallback(async () => {
     setIsPTRing(true)
     try {
       await refetch()
@@ -91,7 +95,7 @@ export const ProfileStarterPacks = React.forwardRef<
     setIsPTRing(false)
   }, [refetch, setIsPTRing])
 
-  const onEndReached = React.useCallback(async () => {
+  const onEndReached = useCallback(async () => {
     if (isFetching || !hasNextPage) return
 
     try {
@@ -101,7 +105,7 @@ export const ProfileStarterPacks = React.forwardRef<
     }
   }, [isFetching, hasNextPage, fetchNextPage])
 
-  React.useEffect(() => {
+  useEffect(() => {
     if (enabled && scrollElRef.current) {
       const nativeTag = findNodeHandle(scrollElRef.current)
       setScrollViewTag(nativeTag)
@@ -140,9 +144,11 @@ export const ProfileStarterPacks = React.forwardRef<
         desktopFixedHeight
         onEndReached={onEndReached}
         onRefresh={onRefresh}
-        ListEmptyComponent={Empty}
+        ListEmptyComponent={
+          data ? (isMe ? Empty : undefined) : FeedLoadingPlaceholder
+        }
         ListFooterComponent={
-          items?.length !== 0 && isMe ? CreateAnother : undefined
+          !!data && items?.length !== 0 && isMe ? CreateAnother : undefined
         }
       />
     </View>
@@ -181,7 +187,6 @@ function CreateAnother() {
 
 function Empty() {
   const {_} = useLingui()
-  const t = useTheme()
   const navigation = useNavigation<NavigationProp>()
   const confirmDialogControl = useDialogControl()
   const followersDialogControl = useDialogControl()
@@ -190,7 +195,7 @@ function Empty() {
   const {needsEmailVerification} = useEmail()
   const verifyEmailControl = useDialogControl()
 
-  const [isGenerating, setIsGenerating] = React.useState(false)
+  const [isGenerating, setIsGenerating] = useState(false)
 
   const {mutate: generateStarterPack} = useGenerateStarterPackMutation({
     onSuccess: ({uri}) => {
@@ -227,16 +232,10 @@ function Empty() {
         a.justify_between,
         a.gap_lg,
         a.shadow_lg,
-        {marginTop: 1},
+        {marginTop: a.border.borderWidth},
       ]}>
       <View style={[a.gap_xs]}>
-        <Text
-          style={[
-            a.font_bold,
-            a.text_lg,
-            t.atoms.text_contrast_medium,
-            {color: 'white'},
-          ]}>
+        <Text style={[a.font_bold, a.text_lg, {color: 'white'}]}>
           <Trans>You haven't created a starter pack yet!</Trans>
         </Text>
         <Text style={[a.text_md, {color: 'white'}]}>