diff --git a/src/components/FeedSuggestedFollows/index.tsx b/src/components/FeedSuggestedFollows/index.tsx index 0c8993f8ce..9d36a524be 100644 --- a/src/components/FeedSuggestedFollows/index.tsx +++ b/src/components/FeedSuggestedFollows/index.tsx @@ -6,21 +6,69 @@ import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useProfileShadow} from '#/state/cache/profile-shadow' -import {useModerationOpts} from '#/state/queries/preferences' +import {useModerationOpts} from '#/state/preferences/moderation-opts' import {useSuggestedFollowsQuery} from '#/state/queries/suggested-follows' import {isJustAMute} from 'lib/moderation' import {sanitizeDisplayName} from 'lib/strings/display-names' import {sanitizeHandle} from 'lib/strings/handles' import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar' import {atoms as a, useTheme} from '#/alf' -import {Button, ButtonIcon} from '#/components/Button' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {useFollowMethods} from '#/components/hooks/useFollowMethods' import {useRichText} from '#/components/hooks/useRichText' +import {ArrowRotateCounterClockwise_Stroke2_Corner0_Rounded as Refresh} from '#/components/icons/ArrowRotateCounterClockwise' import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check' +import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus' import {RichText} from '#/components/RichText' import {Text} from '#/components/Typography' +export function SuggestedFollowCardSkeleton() { + const t = useTheme() + return ( + + + + + + + + + + + + + + + + + + + ) +} + export function SuggestedFollowCard({ profile: profileUnshadowed, }: { @@ -32,10 +80,9 @@ export function SuggestedFollowCard({ const moderationOpts = useModerationOpts() const {follow, unfollow} = useFollowMethods({ profile, - // @ts-ignore TODO - logContext: 'FeedSuggestedFollowsCard', + logContext: 'FeedSuggestedFollowCard', }) - // @ts-ignore TODO + // @ts-ignore TODO why isn't this type correct const [descriptionRT] = useRichText(profileUnshadowed?.description ?? '') if (!moderationOpts) return null @@ -49,7 +96,7 @@ export function SuggestedFollowCard({ a.p_lg, a.rounded_md, a.gap_sm, - t.atoms.bg, + t.atoms.bg_contrast_25, { width: 300, }, @@ -57,8 +104,7 @@ export function SuggestedFollowCard({ @@ -94,7 +140,7 @@ export function SuggestedFollowCard({ size="small" shape="round" variant="solid" - color="secondary" + color="primary" onPress={profile.viewer?.following ? unfollow : follow}> {profile.viewer?.following ? ( @@ -105,16 +151,54 @@ export function SuggestedFollowCard({ - + ) } -export function FeedSuggestedFollows() { +export function ErrorState({retry}: {retry: () => void}) { const t = useTheme() - const {isLoading, data: suggestions, error} = useSuggestedFollowsQuery() + return ( + <> + + + Whoops, something went wrong :( + + + + + + + ) +} + +export function FeedSuggestedFollowsCards() { + const { + isLoading, + data: suggestions, + error, + refetch, + } = useSuggestedFollowsQuery() const profiles: AppBskyActorDefs.ProfileViewBasic[] = [] if (suggestions) { @@ -131,6 +215,28 @@ export function FeedSuggestedFollows() { } } + return ( + + + {isLoading ? ( + Array(3) + .fill(0) + .map((_, i) => ) + ) : error || !profiles.length ? ( + + ) : ( + profiles.map((profile, i) => ( + + )) + )} + + + ) +} + +export function FeedSuggestedFollowsInterstitial() { + const t = useTheme() + return ( @@ -140,17 +246,7 @@ export function FeedSuggestedFollows() { - - - {isLoading - ? null - : error || !profiles.length - ? null - : profiles.map((profile, i) => ( - - ))} - - + ) } diff --git a/src/screens/Home/EmptyTimeline.tsx b/src/screens/Home/EmptyTimeline.tsx new file mode 100644 index 0000000000..b4f538c61e --- /dev/null +++ b/src/screens/Home/EmptyTimeline.tsx @@ -0,0 +1,70 @@ +import React from 'react' +import {View} from 'react-native' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {CenteredView} from '#/view/com/util/Views' +import {atoms as a} from '#/alf' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' +import {FeedSuggestedFollowsCards} from '#/components/FeedSuggestedFollows' +import {IconCircle} from '#/components/IconCircle' +import {ArrowRotateCounterClockwise_Stroke2_Corner0_Rounded as Refresh} from '#/components/icons/ArrowRotateCounterClockwise' +import {FilterTimeline_Stroke2_Corner0_Rounded as FilterTimeline} from '#/components/icons/FilterTimeline' +import {Divider} from '#/components/Menu' +import {Text} from '#/components/Typography' + +export function EmptyTimeline() { + const {_} = useLingui() + + return ( + + + + + + Welcome to your timeline + + + + Your timeline is where you can see posts from people you follow. + It's always chronologically sorted, so you'll never miss a post. + + + + + Follow some people to get started! + + + + + + + + + + + When you're done: + + + + + + + ) +}