From 81ac943450d1249435ff2892535200218f1c8072 Mon Sep 17 00:00:00 2001 From: Hailey Date: Fri, 7 Jun 2024 01:00:00 -0700 Subject: [PATCH] use real data in landing --- src/lib/routes/links.ts | 17 ++ src/lib/routes/types.ts | 3 +- src/routes.ts | 2 +- src/screens/StarterPack/Landing/index.tsx | 251 +++++++++--------- src/screens/StarterPack/Main/ProfilesList.tsx | 9 +- src/screens/StarterPack/Main/index.tsx | 204 ++++++-------- src/state/queries/useStarterPackQuery.ts | 18 +- 7 files changed, 246 insertions(+), 258 deletions(-) diff --git a/src/lib/routes/links.ts b/src/lib/routes/links.ts index 9dfdab909b..66f6530ba1 100644 --- a/src/lib/routes/links.ts +++ b/src/lib/routes/links.ts @@ -1,3 +1,5 @@ +import {AppBskyGraphDefs, AtUri} from '@atproto/api' + import {isInvalidHandle} from 'lib/strings/handles' export function makeProfileLink( @@ -35,3 +37,18 @@ export function makeSearchLink(props: {query: string; from?: 'me' | string}) { props.query + (props.from ? ` from:${props.from}` : ''), )}` } + +export function makeStarterPackLink( + starterPackOrName: + | AppBskyGraphDefs.StarterPackViewBasic + | AppBskyGraphDefs.StarterPackView + | string, + rkey?: string, +) { + if (typeof starterPackOrName === 'string') { + return `/starter-pack/${starterPackOrName}/${rkey}` + } else { + const rkey = new AtUri(starterPackOrName.uri).rkey + return makeProfileLink(starterPackOrName.creator, 'starter-pack', rkey) + } +} diff --git a/src/lib/routes/types.ts b/src/lib/routes/types.ts index e55f4ee287..139115698f 100644 --- a/src/lib/routes/types.ts +++ b/src/lib/routes/types.ts @@ -41,7 +41,7 @@ export type CommonNavigatorParams = { MessagesConversation: {conversation: string; embed?: string} MessagesSettings: undefined StarterPack: {name: string; rkey: string} - StarterPackLanding: {id: string} + StarterPackLanding: {name: string; rkey: string} StarterPackWizard: { mode: 'Create' | 'Edit' id?: string @@ -105,6 +105,7 @@ export type AllNavigatorParams = CommonNavigatorParams & { MessagesTab: undefined Messages: {animation?: 'push' | 'pop'} StarterPack: {name: string; rkey: string} + StarterPackLanding: {name: string; rkey: string} StarterPackWizard: { mode: 'Create' | 'Edit' id?: string diff --git a/src/routes.ts b/src/routes.ts index c06cc8b037..115107d168 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -41,6 +41,6 @@ export const router = new Router({ MessagesSettings: '/messages/settings', MessagesConversation: '/messages/:conversation', StarterPack: '/starter-pack/:name/:rkey', - StarterPackLanding: '/start/:id', + StarterPackLanding: '/start/:name/:rkey', StarterPackWizard: '/starter-pack/create', }) diff --git a/src/screens/StarterPack/Landing/index.tsx b/src/screens/StarterPack/Landing/index.tsx index 2305b78cd0..f4dd406693 100644 --- a/src/screens/StarterPack/Landing/index.tsx +++ b/src/screens/StarterPack/Landing/index.tsx @@ -1,12 +1,18 @@ import React from 'react' import {ScrollView, View} from 'react-native' import {LinearGradient} from 'expo-linear-gradient' +import { + AppBskyActorDefs, + AppBskyGraphDefs, + AppBskyGraphStarterpack, +} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {NativeStackScreenProps} from '@react-navigation/native-stack' import {CommonNavigatorParams} from 'lib/routes/types' -import {useGate} from 'lib/statsig/statsig' +import {useResolveDidQuery} from 'state/queries/resolve-uri' +import {useStarterPackQuery} from 'state/queries/useStarterPackQuery' import {useSetMinimalShellMode} from 'state/shell' import {FeedSourceCard} from 'view/com/feeds/FeedSourceCard' import {UserAvatar} from 'view/com/util/UserAvatar' @@ -15,94 +21,69 @@ import {Logo} from 'view/icons/Logo' import {atoms as a, useTheme} from '#/alf' import {Button, ButtonText} from '#/components/Button' import {Divider} from '#/components/Divider' +import {ListMaybePlaceholder} from '#/components/Lists' import {Text} from '#/components/Typography' -/** - * TEMPORARY CONTENT, DO NOT TRANSLATE - */ -/** - * TEMPORARY CONTENT, DO NOT TRANSLATE - */ -/** - * TEMPORARY CONTENT, DO NOT TRANSLATE - */ - -const PLACEHOLDER_USERS = [ - { - displayName: 'Bossett', - avatar: - 'https://cdn.bsky.app/img/avatar/plain/did:plc:jfhpnnst6flqway4eaeqzj2a/bafkreid42e2su4sju7hl2nm4ouacw3icvvytf7r6gab3pvc2qxhqhc5ji4@jpeg', - }, - { - displayName: 'hailey', - avatar: - 'https://cdn.bsky.app/img/avatar/plain/did:plc:oisofpd7lj26yvgiivf3lxsi/bafkreia4lpswywb5yx3gsezqb5io73kt7icw634ks4m4mmbfvp7e62cxku@jpeg', - }, - { - displayName: 'samuel', - avatar: - 'https://cdn.bsky.app/img/avatar/plain/did:plc:p2cp5gopk7mgjegy6wadk3ep/bafkreias5vktko4jpg4mwp4audptcbdfkb4o3cfyzt4426mj2h7ewwvg7q@jpeg', - }, - - { - displayName: 'Paul โ€œFrazeeโ€ ๐Ÿฆ‹', - avatar: - 'https://cdn.bsky.app/img/avatar/plain/did:plc:ragtjsm2j2vknwkz3zp4oxrd/bafkreihhpqdyntku66himwor5wlhtdo44hllmngj2ofmbqnm25bdm454wq@jpeg', - }, - { - displayName: 'Jay', - avatar: - 'https://cdn.bsky.app/img/avatar/plain/did:plc:oky5czdrnfjpqslsw2a5iclo/bafkreihidru2xruxdxlvvcixc7lbgoudzicjbrdgacdhdhxyfw4yut4nfq@jpeg', - }, - { - displayName: 'Emily ๐Ÿฆ‹', - avatar: - 'https://cdn.bsky.app/img/avatar/plain/did:plc:vjug55kidv6sye7ykr5faxxn/bafkreia63347vwjt4sgfkedgvytodt22ugfck5o36qotwaflsf3qq5xj3y@jpeg', - }, - { - displayName: 'Rose ๐ŸŒน', - avatar: - 'https://cdn.bsky.app/img/avatar/plain/did:plc:qjeavhlw222ppsre4rscd3n2/bafkreiehdi7v7bmz64anqam72ybtkkeodfe22sh7dcsh7m6wei2cf5liye@jpeg', - }, - { - displayName: 'dan', - avatar: - 'https://cdn.bsky.app/img/avatar/plain/did:plc:fpruhuo22xkm5o7ttr2ktxdo/bafkreif65cz6sp4cvwue6dnsy7lhy7o7vdelknwd6hermcbzg2npealz5q@jpeg', - }, -] - export function LandingScreen({ navigation, + route, }: NativeStackScreenProps) { - const {_} = useLingui() - const gate = useGate() - const t = useTheme() + const {name, rkey} = route.params const setMinimalShellMode = useSetMinimalShellMode() + + const { + data: did, + isLoading: isLoadingDid, + isError: isErrorDid, + } = useResolveDidQuery(name) + const { + data: starterPack, + isLoading: isLoadingStarterPack, + isError: isErrorStarterPack, + } = useStarterPackQuery({did, rkey}) + + React.useEffect(() => { + setMinimalShellMode(true) + return () => { + setMinimalShellMode(false) + } + }, [navigation, setMinimalShellMode]) + + if (!did || !starterPack) { + return ( + + ) + } + + return +} + +function LandingScreenInner({ + starterPack, +}: { + starterPack: AppBskyGraphDefs.StarterPackView +}) { + const {record, creator, listItemsSample, feeds, joinedWeekCount} = starterPack + const {_} = useLingui() + const t = useTheme() + const gradient = t.name === 'light' ? [t.palette.primary_500, t.palette.primary_300] : [t.palette.primary_600, t.palette.primary_400] - const userSets = React.useMemo(() => { - return { - first: PLACEHOLDER_USERS.slice(0, 4), - second: PLACEHOLDER_USERS.slice(4, 8), - } - }, []) + const sampleProfiles = listItemsSample?.map(item => item.subject) + const userSets = { + first: sampleProfiles?.slice(0, 4), + second: sampleProfiles?.slice(4, 8), + } - React.useEffect(() => { - if (!gate('starter_packs_enabled')) { - // @ts-expect-error idk - navigation.replace('Home') - return - } - - setMinimalShellMode(true) - - return () => { - setMinimalShellMode(false) - } - }, [gate, navigation, setMinimalShellMode]) + if (!AppBskyGraphStarterpack.isRecord(record)) { + return null + } return ( @@ -117,18 +98,20 @@ export function LandingScreen({ - Science + {record.name} - Starter pack by Bossett + Starter pack by {creator.displayName || `@${creator.handle}`} - - 186 joined this week - + {!!joinedWeekCount && joinedWeekCount >= 50 && ( + + {joinedWeekCount} joined this week! + + )} - (This is the description) A collection of feeds and users to get - you started with the science community on Bluesky! + {record.description} - - Join Bluesky now to subscribe to these feeds: - - - - - - - You'll also follow these people and many others! - - - - - + {!!feeds?.length && ( + <> + + Join Bluesky now to subscribe to these feeds: + + + + + + + )} + + {sampleProfiles?.length && ( + <> + + {feeds?.length ? ( + + You'll also follow these people and many others! + + ) : ( + + Follow these people and many others to get started! + + )} + + + {!!userSets.first?.length && ( + + )} + {!!userSets.second?.length && ( + + )} + + + )} @@ -181,7 +185,7 @@ export function LandingScreen({ ) } -function User({displayName, avatar}: {displayName: string; avatar: string}) { +function User({displayName, avatar}: {displayName: string; avatar?: string}) { return ( @@ -192,13 +196,20 @@ function User({displayName, avatar}: {displayName: string; avatar: string}) { ) } -function UserSet({users}: {users: {displayName: string; avatar: string}[]}) { +function ProfilesSet({ + profiles, +}: { + profiles: AppBskyActorDefs.ProfileViewBasic[] +}) { return ( - - - - + {profiles.map(profile => ( + + ))} ) } diff --git a/src/screens/StarterPack/Main/ProfilesList.tsx b/src/screens/StarterPack/Main/ProfilesList.tsx index 8084e6e643..7ac2ddfe99 100644 --- a/src/screens/StarterPack/Main/ProfilesList.tsx +++ b/src/screens/StarterPack/Main/ProfilesList.tsx @@ -4,6 +4,7 @@ import {AppBskyActorDefs} from '@atproto/api' import {useBottomBarOffset} from 'lib/hooks/useBottomBarOffset' import {isNative} from 'platform/detection' +import {useListMembersQuery} from 'state/queries/list-members' import {ProfileCardWithFollowBtn} from 'view/com/profile/ProfileCard' import {List, ListRef} from 'view/com/util/List' import {SectionRef} from '#/screens/Profile/Sections/types' @@ -17,16 +18,19 @@ function keyExtractor(item: AppBskyActorDefs.ProfileViewBasic, index: number) { } interface ProfilesListProps { - profiles: AppBskyActorDefs.ProfileViewBasic[] + listUri: string headerHeight: number scrollElRef: ListRef } export const ProfilesList = React.forwardRef( - function ProfilesListImpl({profiles, headerHeight, scrollElRef}, ref) { + function ProfilesListImpl({listUri, headerHeight, scrollElRef}, ref) { const [initialHeaderHeight] = React.useState(headerHeight) const bottomBarOffset = useBottomBarOffset(20) + const {data} = useListMembersQuery(listUri) + const profiles = data?.pages.flatMap(p => p.items[0].subject) + const onScrollToTop = useCallback(() => { scrollElRef.current?.scrollToOffset({ animated: isNative, @@ -49,7 +53,6 @@ export const ProfilesList = React.forwardRef( } showsVerticalScrollIndicator={false} - // @ts-ignore desktopFixedHeight /> ) diff --git a/src/screens/StarterPack/Main/index.tsx b/src/screens/StarterPack/Main/index.tsx index 34b91f1e7a..8af6f5ac9e 100644 --- a/src/screens/StarterPack/Main/index.tsx +++ b/src/screens/StarterPack/Main/index.tsx @@ -1,12 +1,17 @@ import React from 'react' import {View} from 'react-native' +import {AppBskyGraphDefs, AppBskyGraphStarterpack} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {NativeStackScreenProps} from '@react-navigation/native-stack' +import {makeProfileLink} from 'lib/routes/links' import {CommonNavigatorParams} from 'lib/routes/types' import {shareUrl} from 'lib/sharing' import {isWeb} from 'platform/detection' +import {useResolveDidQuery} from 'state/queries/resolve-uri' +import {useStarterPackQuery} from 'state/queries/useStarterPackQuery' +import {useSession} from 'state/session' import {PagerWithHeader} from 'view/com/pager/PagerWithHeader' import {ProfileSubpageHeader} from 'view/com/profile/ProfileSubpageHeader' import {CenteredView} from 'view/com/util/Views' @@ -17,148 +22,100 @@ import {Button, ButtonText} from '#/components/Button' import {useDialogControl} from '#/components/Dialog' import {ArrowOutOfBox_Stroke2_Corner0_Rounded as ArrowOutOfBox} from '#/components/icons/ArrowOutOfBox' import {QrCode_Stroke2_Corner0_Rounded as QrCode} from '#/components/icons/QrCode' +import {ListMaybePlaceholder} from '#/components/Lists' import * as Menu from '#/components/Menu' import {QrCodeDialog} from '#/components/StarterPack/QrCodeDialog' import {Text} from '#/components/Typography' -/** - * TEMPORARY CONTENT, DO NOT TRANSLATE - */ -/** - * TEMPORARY CONTENT, DO NOT TRANSLATE - */ -/** - * TEMPORARY CONTENT, DO NOT TRANSLATE - */ +export function StarterPackScreen({ + route, +}: NativeStackScreenProps) { + const {name, rkey} = route.params + const { + data: did, + isLoading: isLoadingDid, + isError: isErrorDid, + } = useResolveDidQuery(name) + const { + data: starterPack, + isLoading: isLoadingStarterPack, + isError: isErrorStarterPack, + } = useStarterPackQuery({did, rkey}) -const PLACEHOLDER_USERS = [ - { - did: 'did:plc:qjeavhlw222ppsre4rscd3n2', - handle: 'test.handle', - displayName: 'Bossett', - avatar: - 'https://cdn.bsky.app/img/avatar/plain/did:plc:jfhpnnst6flqway4eaeqzj2a/bafkreid42e2su4sju7hl2nm4ouacw3icvvytf7r6gab3pvc2qxhqhc5ji4@jpeg', - description: 'he/him\n' + '๐Ÿ“ ๐Ÿ‡ฆ๐Ÿ‡บ', - }, - { - did: 'did:plc:qjeavhlw222ppsre4rscd3n2', - handle: 'test.handle', - displayName: 'hailey', - avatar: - 'https://cdn.bsky.app/img/avatar/plain/did:plc:oisofpd7lj26yvgiivf3lxsi/bafkreia4lpswywb5yx3gsezqb5io73kt7icw634ks4m4mmbfvp7e62cxku@jpeg', - description: - 'React Native @ Bluesky\n' + 'Tomato hater ๐Ÿ… โŒ\n' + 'she/her', - }, - { - did: 'did:plc:qjeavhlw222ppsre4rscd3n2', - handle: 'test.handle', - displayName: 'samuel', - avatar: - 'https://cdn.bsky.app/img/avatar/plain/did:plc:p2cp5gopk7mgjegy6wadk3ep/bafkreias5vktko4jpg4mwp4audptcbdfkb4o3cfyzt4426mj2h7ewwvg7q@jpeg', - description: 'formerly mozzius. developer at bluesky\n' + '๐Ÿ“London', - }, + if (!did || !starterPack) { + return ( + + ) + } - { - did: 'did:plc:qjeavhlw222ppsre4rscd3n2', - handle: 'test.handle', - displayName: 'Paul โ€œFrazeeโ€ ๐Ÿฆ‹', - avatar: - 'https://cdn.bsky.app/img/avatar/plain/did:plc:ragtjsm2j2vknwkz3zp4oxrd/bafkreihhpqdyntku66himwor5wlhtdo44hllmngj2ofmbqnm25bdm454wq@jpeg', - description: 'Developer at Bluesky. Go Mets.', - }, - { - did: 'did:plc:qjeavhlw222ppsre4rscd3n2', - handle: 'test.handle', - displayName: 'Jay', - avatar: - 'https://cdn.bsky.app/img/avatar/plain/did:plc:oky5czdrnfjpqslsw2a5iclo/bafkreihidru2xruxdxlvvcixc7lbgoudzicjbrdgacdhdhxyfw4yut4nfq@jpeg', - }, - { - did: 'did:plc:qjeavhlw222ppsre4rscd3n2', - handle: 'test.handle', - displayName: 'Emily ๐Ÿฆ‹', - avatar: - 'https://cdn.bsky.app/img/avatar/plain/did:plc:vjug55kidv6sye7ykr5faxxn/bafkreia63347vwjt4sgfkedgvytodt22ugfck5o36qotwaflsf3qq5xj3y@jpeg', - }, - { - did: 'did:plc:qjeavhlw222ppsre4rscd3n2', - handle: 'test.handle', - displayName: 'Rose ๐ŸŒน', - avatar: - 'https://cdn.bsky.app/img/avatar/plain/did:plc:qjeavhlw222ppsre4rscd3n2/bafkreiehdi7v7bmz64anqam72ybtkkeodfe22sh7dcsh7m6wei2cf5liye@jpeg', - }, - { - did: 'did:plc:qjeavhlw222ppsre4rscd3n2', - handle: 'test.handle', - displayName: 'dan', - avatar: - 'https://cdn.bsky.app/img/avatar/plain/did:plc:fpruhuo22xkm5o7ttr2ktxdo/bafkreif65cz6sp4cvwue6dnsy7lhy7o7vdelknwd6hermcbzg2npealz5q@jpeg', - }, -] - -const PLACEHOLDER_FEEDS = [ - 'at://did:plc:jfhpnnst6flqway4eaeqzj2a/app.bsky.feed.generator/for-science', - 'at://did:plc:upmfcx5muayjhkg5sltj625o/app.bsky.feed.generator/aaachrckxlsh2', -] - -export function StarterPackScreen({}: NativeStackScreenProps< - CommonNavigatorParams, - 'StarterPackLanding' ->) { - // const {id} = route.params + const items = [ + ...(starterPack.list ? ['People'] : []), + ...(starterPack.feeds ? ['Feeds'] : []), + ] return ( - + +
}> + {starterPack.list + ? ({headerHeight, scrollElRef}) => ( + + ) + : null} + {starterPack.feeds + ? ({headerHeight, scrollElRef}) => ( + + ) + : null} + + ) } -function StarterPackScreenInner() { - const isOwn = true - - return ( - -
}> - {({headerHeight, scrollElRef}) => ( - - )} - {({headerHeight, scrollElRef}) => ( - - )} - - - ) -} - -function Header({isOwn}: {isOwn: boolean}) { +function Header({ + starterPack, +}: { + starterPack: AppBskyGraphDefs.StarterPackView +}) { const {_} = useLingui() + const {currentAccount} = useSession() const qrCodeDialogControl = useDialogControl() + const {record, creator} = starterPack + const isOwn = creator.did === currentAccount?.did + + if (!AppBskyGraphStarterpack.isRecord(record)) { + return null + } + return ( <> @@ -218,10 +175,7 @@ function Header({isOwn}: {isOwn: boolean}) { - - (This is the description) A collection of feeds and users to get you - started with the science community on Bluesky! - + {record.description} diff --git a/src/state/queries/useStarterPackQuery.ts b/src/state/queries/useStarterPackQuery.ts index 46f71f2fb5..c03691acbf 100644 --- a/src/state/queries/useStarterPackQuery.ts +++ b/src/state/queries/useStarterPackQuery.ts @@ -1,22 +1,24 @@ -import {AppBskyGraphGetStarterPack} from '@atproto/api' -import {useMutation} from '@tanstack/react-query' -import {useQuery} from 'react-query' +import {StarterPackView} from '@atproto/api/dist/client/types/app/bsky/graph/defs' +import {useMutation, useQuery} from '@tanstack/react-query' import {STALE} from 'state/queries/index' import {useAgent, useSession} from 'state/session' const RQKEY_ROOT = 'starter-pack' -export function useStarterPackQuery({id}: {id: string}) { +export function useStarterPackQuery({did, rkey}: {did?: string; rkey: string}) { const agent = useAgent() - return useQuery({ - queryKey: [RQKEY_ROOT, id], + const uri = `at://${did}/app.bsky.graph.starterpack/${rkey}` + + return useQuery({ + queryKey: [RQKEY_ROOT, did, rkey], queryFn: async () => { const res = await agent.app.bsky.graph.getStarterPack({ - starterPack: id, + starterPack: uri, }) - return res.data + return res.data.starterPack }, + enabled: Boolean(did), staleTime: STALE.MINUTES.FIVE, }) }