about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/view/com/post-thread/PostLikedBy.tsx103
-rw-r--r--src/view/com/post-thread/PostRepostedBy.tsx104
-rw-r--r--src/view/screens/PostLikedBy.tsx15
-rw-r--r--src/view/screens/PostRepostedBy.tsx15
-rw-r--r--src/view/screens/ProfileFeedLikedBy.tsx15
5 files changed, 127 insertions, 125 deletions
diff --git a/src/view/com/post-thread/PostLikedBy.tsx b/src/view/com/post-thread/PostLikedBy.tsx
index 0760ed7ff..da230aade 100644
--- a/src/view/com/post-thread/PostLikedBy.tsx
+++ b/src/view/com/post-thread/PostLikedBy.tsx
@@ -1,38 +1,57 @@
 import React, {useCallback, useMemo, useState} from 'react'
-import {ActivityIndicator, StyleSheet, View} from 'react-native'
 import {AppBskyFeedGetLikes as GetLikes} from '@atproto/api'
-import {CenteredView} from '../util/Views'
-import {List} from '../util/List'
-import {ErrorMessage} from '../util/error/ErrorMessage'
-import {ProfileCardWithFollowBtn} from '../profile/ProfileCard'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+
+import {cleanError} from '#/lib/strings/errors'
 import {logger} from '#/logger'
-import {LoadingScreen} from '../util/LoadingScreen'
-import {useResolveUriQuery} from '#/state/queries/resolve-uri'
 import {useLikedByQuery} from '#/state/queries/post-liked-by'
-import {cleanError} from '#/lib/strings/errors'
+import {useResolveUriQuery} from '#/state/queries/resolve-uri'
+import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender'
+import {
+  ListFooter,
+  ListHeaderDesktop,
+  ListMaybePlaceholder,
+} from '#/components/Lists'
+import {ProfileCardWithFollowBtn} from '../profile/ProfileCard'
+import {List} from '../util/List'
+
+function renderItem({item}: {item: GetLikes.Like}) {
+  return <ProfileCardWithFollowBtn key={item.actor.did} profile={item.actor} />
+}
+
+function keyExtractor(item: GetLikes.Like) {
+  return item.actor.did
+}
 
 export function PostLikedBy({uri}: {uri: string}) {
+  const {_} = useLingui()
+  const initialNumToRender = useInitialNumToRender()
+
   const [isPTRing, setIsPTRing] = useState(false)
+
   const {
     data: resolvedUri,
     error: resolveError,
-    isFetching: isFetchingResolvedUri,
+    isLoading: isLoadingUri,
   } = useResolveUriQuery(uri)
   const {
     data,
-    isFetching,
-    isFetched,
+    isLoading: isLoadingLikes,
     isFetchingNextPage,
     hasNextPage,
     fetchNextPage,
-    isError,
     error,
     refetch,
   } = useLikedByQuery(resolvedUri?.uri)
+
+  const isError = Boolean(resolveError || error)
+
   const likes = useMemo(() => {
     if (data?.pages) {
       return data.pages.flatMap(page => page.likes)
     }
+    return []
   }, [data])
 
   const onRefresh = useCallback(async () => {
@@ -46,64 +65,44 @@ export function PostLikedBy({uri}: {uri: string}) {
   }, [refetch, setIsPTRing])
 
   const onEndReached = useCallback(async () => {
-    if (isFetching || !hasNextPage || isError) return
+    if (isFetchingNextPage || !hasNextPage || isError) return
     try {
       await fetchNextPage()
     } catch (err) {
       logger.error('Failed to load more likes', {message: err})
     }
-  }, [isFetching, hasNextPage, isError, fetchNextPage])
+  }, [isFetchingNextPage, hasNextPage, isError, fetchNextPage])
 
-  const renderItem = useCallback(({item}: {item: GetLikes.Like}) => {
+  if (likes.length < 1) {
     return (
-      <ProfileCardWithFollowBtn key={item.actor.did} profile={item.actor} />
+      <ListMaybePlaceholder
+        isLoading={isLoadingUri || isLoadingLikes}
+        isError={isError}
+      />
     )
-  }, [])
-
-  if (isFetchingResolvedUri || !isFetched) {
-    return <LoadingScreen />
   }
 
-  // error
-  // =
-  if (resolveError || isError) {
-    return (
-      <CenteredView>
-        <ErrorMessage
-          message={cleanError(resolveError || error)}
-          onPressTryAgain={onRefresh}
-        />
-      </CenteredView>
-    )
-  }
-
-  // loaded
-  // =
   return (
     <List
       data={likes}
-      keyExtractor={item => item.actor.did}
+      renderItem={renderItem}
+      keyExtractor={keyExtractor}
       refreshing={isPTRing}
       onRefresh={onRefresh}
       onEndReached={onEndReached}
-      renderItem={renderItem}
-      initialNumToRender={15}
-      // FIXME(dan)
-      // eslint-disable-next-line react/no-unstable-nested-components
-      ListFooterComponent={() => (
-        <View style={styles.footer}>
-          {(isFetching || isFetchingNextPage) && <ActivityIndicator />}
-        </View>
-      )}
+      onEndReachedThreshold={4}
+      ListHeaderComponent={<ListHeaderDesktop title={_(msg`Liked By`)} />}
+      ListFooterComponent={
+        <ListFooter
+          isFetchingNextPage={isFetchingNextPage}
+          error={cleanError(error)}
+          onRetry={fetchNextPage}
+        />
+      }
       // @ts-ignore our .web version only -prf
       desktopFixedHeight
+      initialNumToRender={initialNumToRender}
+      windowSize={11}
     />
   )
 }
-
-const styles = StyleSheet.create({
-  footer: {
-    height: 200,
-    paddingTop: 20,
-  },
-})
diff --git a/src/view/com/post-thread/PostRepostedBy.tsx b/src/view/com/post-thread/PostRepostedBy.tsx
index 31a0be832..9038549a5 100644
--- a/src/view/com/post-thread/PostRepostedBy.tsx
+++ b/src/view/com/post-thread/PostRepostedBy.tsx
@@ -1,38 +1,57 @@
-import React, {useMemo, useCallback, useState} from 'react'
-import {ActivityIndicator, StyleSheet, View} from 'react-native'
+import React, {useCallback, useMemo, useState} from 'react'
 import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
-import {CenteredView} from '../util/Views'
-import {List} from '../util/List'
-import {ProfileCardWithFollowBtn} from '../profile/ProfileCard'
-import {ErrorMessage} from '../util/error/ErrorMessage'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+
+import {cleanError} from '#/lib/strings/errors'
 import {logger} from '#/logger'
-import {LoadingScreen} from '../util/LoadingScreen'
-import {useResolveUriQuery} from '#/state/queries/resolve-uri'
 import {usePostRepostedByQuery} from '#/state/queries/post-reposted-by'
-import {cleanError} from '#/lib/strings/errors'
+import {useResolveUriQuery} from '#/state/queries/resolve-uri'
+import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender'
+import {
+  ListFooter,
+  ListHeaderDesktop,
+  ListMaybePlaceholder,
+} from '#/components/Lists'
+import {ProfileCardWithFollowBtn} from '../profile/ProfileCard'
+import {List} from '../util/List'
+
+function renderItem({item}: {item: ActorDefs.ProfileViewBasic}) {
+  return <ProfileCardWithFollowBtn key={item.did} profile={item} />
+}
+
+function keyExtractor(item: ActorDefs.ProfileViewBasic) {
+  return item.did
+}
 
 export function PostRepostedBy({uri}: {uri: string}) {
+  const {_} = useLingui()
+  const initialNumToRender = useInitialNumToRender()
+
   const [isPTRing, setIsPTRing] = useState(false)
+
   const {
     data: resolvedUri,
     error: resolveError,
-    isFetching: isFetchingResolvedUri,
+    isLoading: isLoadingUri,
   } = useResolveUriQuery(uri)
   const {
     data,
-    isFetching,
-    isFetched,
+    isLoading: isLoadingRepostedBy,
     isFetchingNextPage,
     hasNextPage,
     fetchNextPage,
-    isError,
     error,
     refetch,
   } = usePostRepostedByQuery(resolvedUri?.uri)
+
+  const isError = Boolean(resolveError || error)
+
   const repostedBy = useMemo(() => {
     if (data?.pages) {
       return data.pages.flatMap(page => page.repostedBy)
     }
+    return []
   }, [data])
 
   const onRefresh = useCallback(async () => {
@@ -46,35 +65,20 @@ export function PostRepostedBy({uri}: {uri: string}) {
   }, [refetch, setIsPTRing])
 
   const onEndReached = useCallback(async () => {
-    if (isFetching || !hasNextPage || isError) return
+    if (isFetchingNextPage || !hasNextPage || isError) return
     try {
       await fetchNextPage()
     } catch (err) {
       logger.error('Failed to load more reposts', {message: err})
     }
-  }, [isFetching, hasNextPage, isError, fetchNextPage])
-
-  const renderItem = useCallback(
-    ({item}: {item: ActorDefs.ProfileViewBasic}) => {
-      return <ProfileCardWithFollowBtn key={item.did} profile={item} />
-    },
-    [],
-  )
-
-  if (isFetchingResolvedUri || !isFetched) {
-    return <LoadingScreen />
-  }
+  }, [isFetchingNextPage, hasNextPage, isError, fetchNextPage])
 
-  // error
-  // =
-  if (resolveError || isError) {
+  if (repostedBy.length < 1) {
     return (
-      <CenteredView>
-        <ErrorMessage
-          message={cleanError(resolveError || error)}
-          onPressTryAgain={onRefresh}
-        />
-      </CenteredView>
+      <ListMaybePlaceholder
+        isLoading={isLoadingUri || isLoadingRepostedBy}
+        isError={isError}
+      />
     )
   }
 
@@ -83,28 +87,24 @@ export function PostRepostedBy({uri}: {uri: string}) {
   return (
     <List
       data={repostedBy}
-      keyExtractor={item => item.did}
+      renderItem={renderItem}
+      keyExtractor={keyExtractor}
       refreshing={isPTRing}
       onRefresh={onRefresh}
       onEndReached={onEndReached}
-      renderItem={renderItem}
-      initialNumToRender={15}
-      // FIXME(dan)
-      // eslint-disable-next-line react/no-unstable-nested-components
-      ListFooterComponent={() => (
-        <View style={styles.footer}>
-          {(isFetching || isFetchingNextPage) && <ActivityIndicator />}
-        </View>
-      )}
+      onEndReachedThreshold={4}
+      ListHeaderComponent={<ListHeaderDesktop title={_(msg`Reposted By`)} />}
+      ListFooterComponent={
+        <ListFooter
+          isFetchingNextPage={isFetchingNextPage}
+          error={cleanError(error)}
+          onRetry={fetchNextPage}
+        />
+      }
       // @ts-ignore our .web version only -prf
       desktopFixedHeight
+      initialNumToRender={initialNumToRender}
+      windowSize={11}
     />
   )
 }
-
-const styles = StyleSheet.create({
-  footer: {
-    height: 200,
-    paddingTop: 20,
-  },
-})
diff --git a/src/view/screens/PostLikedBy.tsx b/src/view/screens/PostLikedBy.tsx
index 604301544..5ff5a1932 100644
--- a/src/view/screens/PostLikedBy.tsx
+++ b/src/view/screens/PostLikedBy.tsx
@@ -1,13 +1,14 @@
 import React from 'react'
 import {View} from 'react-native'
-import {useFocusEffect} from '@react-navigation/native'
-import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
-import {ViewHeader} from '../com/util/ViewHeader'
-import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy'
-import {makeRecordUri} from 'lib/strings/url-helpers'
-import {useSetMinimalShellMode} from '#/state/shell'
 import {msg} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
+import {useFocusEffect} from '@react-navigation/native'
+
+import {useSetMinimalShellMode} from '#/state/shell'
+import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types'
+import {makeRecordUri} from 'lib/strings/url-helpers'
+import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy'
+import {ViewHeader} from '../com/util/ViewHeader'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostLikedBy'>
 export const PostLikedByScreen = ({route}: Props) => {
@@ -23,7 +24,7 @@ export const PostLikedByScreen = ({route}: Props) => {
   )
 
   return (
-    <View>
+    <View style={{flex: 1}}>
       <ViewHeader title={_(msg`Liked By`)} />
       <PostLikedByComponent uri={uri} />
     </View>
diff --git a/src/view/screens/PostRepostedBy.tsx b/src/view/screens/PostRepostedBy.tsx
index 07017d692..eaacc6780 100644
--- a/src/view/screens/PostRepostedBy.tsx
+++ b/src/view/screens/PostRepostedBy.tsx
@@ -1,13 +1,14 @@
 import React from 'react'
 import {View} from 'react-native'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useFocusEffect} from '@react-navigation/native'
-import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
-import {ViewHeader} from '../com/util/ViewHeader'
-import {PostRepostedBy as PostRepostedByComponent} from '../com/post-thread/PostRepostedBy'
-import {makeRecordUri} from 'lib/strings/url-helpers'
+
 import {useSetMinimalShellMode} from '#/state/shell'
-import {useLingui} from '@lingui/react'
-import {msg} from '@lingui/macro'
+import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types'
+import {makeRecordUri} from 'lib/strings/url-helpers'
+import {PostRepostedBy as PostRepostedByComponent} from '../com/post-thread/PostRepostedBy'
+import {ViewHeader} from '../com/util/ViewHeader'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostRepostedBy'>
 export const PostRepostedByScreen = ({route}: Props) => {
@@ -23,7 +24,7 @@ export const PostRepostedByScreen = ({route}: Props) => {
   )
 
   return (
-    <View>
+    <View style={{flex: 1}}>
       <ViewHeader title={_(msg`Reposted By`)} />
       <PostRepostedByComponent uri={uri} />
     </View>
diff --git a/src/view/screens/ProfileFeedLikedBy.tsx b/src/view/screens/ProfileFeedLikedBy.tsx
index b1bcf48ba..bb9ec2bae 100644
--- a/src/view/screens/ProfileFeedLikedBy.tsx
+++ b/src/view/screens/ProfileFeedLikedBy.tsx
@@ -1,13 +1,14 @@
 import React from 'react'
 import {View} from 'react-native'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useFocusEffect} from '@react-navigation/native'
-import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
-import {ViewHeader} from '../com/util/ViewHeader'
-import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy'
-import {makeRecordUri} from 'lib/strings/url-helpers'
+
 import {useSetMinimalShellMode} from '#/state/shell'
-import {useLingui} from '@lingui/react'
-import {msg} from '@lingui/macro'
+import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types'
+import {makeRecordUri} from 'lib/strings/url-helpers'
+import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy'
+import {ViewHeader} from '../com/util/ViewHeader'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFeedLikedBy'>
 export const ProfileFeedLikedByScreen = ({route}: Props) => {
@@ -23,7 +24,7 @@ export const ProfileFeedLikedByScreen = ({route}: Props) => {
   )
 
   return (
-    <View>
+    <View style={{flex: 1}}>
       <ViewHeader title={_(msg`Liked By`)} />
       <PostLikedByComponent uri={uri} />
     </View>