use real data in landing

This commit is contained in:
Hailey
2024-06-07 01:00:00 -07:00
parent 48d2b17fd6
commit 81ac943450
7 changed files with 246 additions and 258 deletions
+17
View File
@@ -1,3 +1,5 @@
import {AppBskyGraphDefs, AtUri} from '@atproto/api'
import {isInvalidHandle} from 'lib/strings/handles' import {isInvalidHandle} from 'lib/strings/handles'
export function makeProfileLink( export function makeProfileLink(
@@ -35,3 +37,18 @@ export function makeSearchLink(props: {query: string; from?: 'me' | string}) {
props.query + (props.from ? ` from:${props.from}` : ''), 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)
}
}
+2 -1
View File
@@ -41,7 +41,7 @@ export type CommonNavigatorParams = {
MessagesConversation: {conversation: string; embed?: string} MessagesConversation: {conversation: string; embed?: string}
MessagesSettings: undefined MessagesSettings: undefined
StarterPack: {name: string; rkey: string} StarterPack: {name: string; rkey: string}
StarterPackLanding: {id: string} StarterPackLanding: {name: string; rkey: string}
StarterPackWizard: { StarterPackWizard: {
mode: 'Create' | 'Edit' mode: 'Create' | 'Edit'
id?: string id?: string
@@ -105,6 +105,7 @@ export type AllNavigatorParams = CommonNavigatorParams & {
MessagesTab: undefined MessagesTab: undefined
Messages: {animation?: 'push' | 'pop'} Messages: {animation?: 'push' | 'pop'}
StarterPack: {name: string; rkey: string} StarterPack: {name: string; rkey: string}
StarterPackLanding: {name: string; rkey: string}
StarterPackWizard: { StarterPackWizard: {
mode: 'Create' | 'Edit' mode: 'Create' | 'Edit'
id?: string id?: string
+1 -1
View File
@@ -41,6 +41,6 @@ export const router = new Router({
MessagesSettings: '/messages/settings', MessagesSettings: '/messages/settings',
MessagesConversation: '/messages/:conversation', MessagesConversation: '/messages/:conversation',
StarterPack: '/starter-pack/:name/:rkey', StarterPack: '/starter-pack/:name/:rkey',
StarterPackLanding: '/start/:id', StarterPackLanding: '/start/:name/:rkey',
StarterPackWizard: '/starter-pack/create', StarterPackWizard: '/starter-pack/create',
}) })
+131 -120
View File
@@ -1,12 +1,18 @@
import React from 'react' import React from 'react'
import {ScrollView, View} from 'react-native' import {ScrollView, View} from 'react-native'
import {LinearGradient} from 'expo-linear-gradient' import {LinearGradient} from 'expo-linear-gradient'
import {
AppBskyActorDefs,
AppBskyGraphDefs,
AppBskyGraphStarterpack,
} from '@atproto/api'
import {msg, Trans} from '@lingui/macro' import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {NativeStackScreenProps} from '@react-navigation/native-stack' import {NativeStackScreenProps} from '@react-navigation/native-stack'
import {CommonNavigatorParams} from 'lib/routes/types' 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 {useSetMinimalShellMode} from 'state/shell'
import {FeedSourceCard} from 'view/com/feeds/FeedSourceCard' import {FeedSourceCard} from 'view/com/feeds/FeedSourceCard'
import {UserAvatar} from 'view/com/util/UserAvatar' 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 {atoms as a, useTheme} from '#/alf'
import {Button, ButtonText} from '#/components/Button' import {Button, ButtonText} from '#/components/Button'
import {Divider} from '#/components/Divider' import {Divider} from '#/components/Divider'
import {ListMaybePlaceholder} from '#/components/Lists'
import {Text} from '#/components/Typography' 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({ export function LandingScreen({
navigation, navigation,
route,
}: NativeStackScreenProps<CommonNavigatorParams, 'StarterPackLanding'>) { }: NativeStackScreenProps<CommonNavigatorParams, 'StarterPackLanding'>) {
const {_} = useLingui() const {name, rkey} = route.params
const gate = useGate()
const t = useTheme()
const setMinimalShellMode = useSetMinimalShellMode() 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 (
<ListMaybePlaceholder
isLoading={isLoadingDid || isLoadingStarterPack}
isError={isErrorDid || isErrorStarterPack}
/>
)
}
return <LandingScreenInner starterPack={starterPack} />
}
function LandingScreenInner({
starterPack,
}: {
starterPack: AppBskyGraphDefs.StarterPackView
}) {
const {record, creator, listItemsSample, feeds, joinedWeekCount} = starterPack
const {_} = useLingui()
const t = useTheme()
const gradient = const gradient =
t.name === 'light' t.name === 'light'
? [t.palette.primary_500, t.palette.primary_300] ? [t.palette.primary_500, t.palette.primary_300]
: [t.palette.primary_600, t.palette.primary_400] : [t.palette.primary_600, t.palette.primary_400]
const userSets = React.useMemo(() => { const sampleProfiles = listItemsSample?.map(item => item.subject)
return { const userSets = {
first: PLACEHOLDER_USERS.slice(0, 4), first: sampleProfiles?.slice(0, 4),
second: PLACEHOLDER_USERS.slice(4, 8), second: sampleProfiles?.slice(4, 8),
} }
}, [])
React.useEffect(() => { if (!AppBskyGraphStarterpack.isRecord(record)) {
if (!gate('starter_packs_enabled')) { return null
// @ts-expect-error idk }
navigation.replace('Home')
return
}
setMinimalShellMode(true)
return () => {
setMinimalShellMode(false)
}
}, [gate, navigation, setMinimalShellMode])
return ( return (
<CenteredView style={a.flex_1}> <CenteredView style={a.flex_1}>
@@ -117,18 +98,20 @@ export function LandingScreen({
</View> </View>
<View style={[a.align_center, a.gap_xs]}> <View style={[a.align_center, a.gap_xs]}>
<Text style={[a.font_bold, a.text_5xl, {color: 'white'}]}> <Text style={[a.font_bold, a.text_5xl, {color: 'white'}]}>
Science {record.name}
</Text> </Text>
<Text style={[a.font_bold, a.text_md, {color: 'white'}]}> <Text style={[a.font_bold, a.text_md, {color: 'white'}]}>
Starter pack by Bossett Starter pack by {creator.displayName || `@${creator.handle}`}
</Text> </Text>
</View> </View>
</LinearGradient> </LinearGradient>
<View style={[a.gap_md, a.mt_lg, a.mx_lg]}> <View style={[a.gap_md, a.mt_lg, a.mx_lg]}>
<Text {!!joinedWeekCount && joinedWeekCount >= 50 && (
style={[a.text_md, a.text_center, t.atoms.text_contrast_medium]}> <Text
186 joined this week style={[a.text_md, a.text_center, t.atoms.text_contrast_medium]}>
</Text> {joinedWeekCount} joined this week!
</Text>
)}
<Button <Button
label={_(msg`Join Bluesky now`)} label={_(msg`Join Bluesky now`)}
onPress={() => {}} onPress={() => {}}
@@ -141,39 +124,60 @@ export function LandingScreen({
</Button> </Button>
<View style={[a.gap_xl, a.mt_md]}> <View style={[a.gap_xl, a.mt_md]}>
<Text style={[a.text_md, t.atoms.text_contrast_medium]}> <Text style={[a.text_md, t.atoms.text_contrast_medium]}>
(This is the description) A collection of feeds and users to get {record.description}
you started with the science community on Bluesky!
</Text> </Text>
<Divider /> <Divider />
<Text style={[a.text_md, t.atoms.text_contrast_medium]}> {!!feeds?.length && (
Join Bluesky now to subscribe to these feeds: <>
</Text> <Text style={[a.text_md, t.atoms.text_contrast_medium]}>
<View <Trans>Join Bluesky now to subscribe to these feeds:</Trans>
style={[ </Text>
t.atoms.bg_contrast_25, <View
a.rounded_sm, style={[
{pointerEvents: 'none'}, t.atoms.bg_contrast_25,
]}> a.rounded_sm,
<FeedSourceCard {pointerEvents: 'none'},
feedUri="at://did:plc:jfhpnnst6flqway4eaeqzj2a/app.bsky.feed.generator/for-science" ]}>
hideTopBorder={true} <FeedSourceCard
/> feedUri="at://did:plc:jfhpnnst6flqway4eaeqzj2a/app.bsky.feed.generator/for-science"
<FeedSourceCard feedUri="at://did:plc:upmfcx5muayjhkg5sltj625o/app.bsky.feed.generator/aaachrckxlsh2" /> hideTopBorder={true}
</View> />
<Text style={[a.mt_sm, a.text_md, t.atoms.text_contrast_medium]}> <FeedSourceCard feedUri="at://did:plc:upmfcx5muayjhkg5sltj625o/app.bsky.feed.generator/aaachrckxlsh2" />
You'll also follow these people and many others! </View>
</Text> </>
<View )}
style={[
t.atoms.bg_contrast_25, {sampleProfiles?.length && (
a.rounded_sm, <>
a.px_xs, <Text
a.py_md, style={[a.mt_sm, a.text_md, t.atoms.text_contrast_medium]}>
a.gap_xl, {feeds?.length ? (
]}> <Trans>
<UserSet users={userSets.first} /> You'll also follow these people and many others!
<UserSet users={userSets.second} /> </Trans>
</View> ) : (
<Trans>
Follow these people and many others to get started!
</Trans>
)}
</Text>
<View
style={[
t.atoms.bg_contrast_25,
a.rounded_sm,
a.px_xs,
a.py_md,
a.gap_xl,
]}>
{!!userSets.first?.length && (
<ProfilesSet profiles={userSets.first} />
)}
{!!userSets.second?.length && (
<ProfilesSet profiles={userSets.second} />
)}
</View>
</>
)}
</View> </View>
</View> </View>
</ScrollView> </ScrollView>
@@ -181,7 +185,7 @@ export function LandingScreen({
) )
} }
function User({displayName, avatar}: {displayName: string; avatar: string}) { function User({displayName, avatar}: {displayName: string; avatar?: string}) {
return ( return (
<View style={[a.flex_1, a.align_center, a.gap_sm]}> <View style={[a.flex_1, a.align_center, a.gap_sm]}>
<UserAvatar size={64} avatar={avatar} /> <UserAvatar size={64} avatar={avatar} />
@@ -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 ( return (
<View style={[a.flex_row, a.gap_xs, a.align_center, a.justify_between]}> <View style={[a.flex_row, a.gap_xs, a.align_center, a.justify_between]}>
<User displayName={users[0].displayName} avatar={users[0].avatar} /> {profiles.map(profile => (
<User displayName={users[1].displayName} avatar={users[1].avatar} /> <User
<User displayName={users[2].displayName} avatar={users[2].avatar} /> key={profile.did}
<User displayName={users[3].displayName} avatar={users[3].avatar} /> displayName={profile.displayName || `@${profile.handle}`}
avatar={profile.avatar}
/>
))}
</View> </View>
) )
} }
@@ -4,6 +4,7 @@ import {AppBskyActorDefs} from '@atproto/api'
import {useBottomBarOffset} from 'lib/hooks/useBottomBarOffset' import {useBottomBarOffset} from 'lib/hooks/useBottomBarOffset'
import {isNative} from 'platform/detection' import {isNative} from 'platform/detection'
import {useListMembersQuery} from 'state/queries/list-members'
import {ProfileCardWithFollowBtn} from 'view/com/profile/ProfileCard' import {ProfileCardWithFollowBtn} from 'view/com/profile/ProfileCard'
import {List, ListRef} from 'view/com/util/List' import {List, ListRef} from 'view/com/util/List'
import {SectionRef} from '#/screens/Profile/Sections/types' import {SectionRef} from '#/screens/Profile/Sections/types'
@@ -17,16 +18,19 @@ function keyExtractor(item: AppBskyActorDefs.ProfileViewBasic, index: number) {
} }
interface ProfilesListProps { interface ProfilesListProps {
profiles: AppBskyActorDefs.ProfileViewBasic[] listUri: string
headerHeight: number headerHeight: number
scrollElRef: ListRef scrollElRef: ListRef
} }
export const ProfilesList = React.forwardRef<SectionRef, ProfilesListProps>( export const ProfilesList = React.forwardRef<SectionRef, ProfilesListProps>(
function ProfilesListImpl({profiles, headerHeight, scrollElRef}, ref) { function ProfilesListImpl({listUri, headerHeight, scrollElRef}, ref) {
const [initialHeaderHeight] = React.useState(headerHeight) const [initialHeaderHeight] = React.useState(headerHeight)
const bottomBarOffset = useBottomBarOffset(20) const bottomBarOffset = useBottomBarOffset(20)
const {data} = useListMembersQuery(listUri)
const profiles = data?.pages.flatMap(p => p.items[0].subject)
const onScrollToTop = useCallback(() => { const onScrollToTop = useCallback(() => {
scrollElRef.current?.scrollToOffset({ scrollElRef.current?.scrollToOffset({
animated: isNative, animated: isNative,
@@ -49,7 +53,6 @@ export const ProfilesList = React.forwardRef<SectionRef, ProfilesListProps>(
<View style={[{height: initialHeaderHeight + bottomBarOffset}]} /> <View style={[{height: initialHeaderHeight + bottomBarOffset}]} />
} }
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
// @ts-ignore
desktopFixedHeight desktopFixedHeight
/> />
) )
+79 -125
View File
@@ -1,12 +1,17 @@
import React from 'react' import React from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import {AppBskyGraphDefs, AppBskyGraphStarterpack} from '@atproto/api'
import {msg, Trans} from '@lingui/macro' import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {NativeStackScreenProps} from '@react-navigation/native-stack' import {NativeStackScreenProps} from '@react-navigation/native-stack'
import {makeProfileLink} from 'lib/routes/links'
import {CommonNavigatorParams} from 'lib/routes/types' import {CommonNavigatorParams} from 'lib/routes/types'
import {shareUrl} from 'lib/sharing' import {shareUrl} from 'lib/sharing'
import {isWeb} from 'platform/detection' 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 {PagerWithHeader} from 'view/com/pager/PagerWithHeader'
import {ProfileSubpageHeader} from 'view/com/profile/ProfileSubpageHeader' import {ProfileSubpageHeader} from 'view/com/profile/ProfileSubpageHeader'
import {CenteredView} from 'view/com/util/Views' import {CenteredView} from 'view/com/util/Views'
@@ -17,148 +22,100 @@ import {Button, ButtonText} from '#/components/Button'
import {useDialogControl} from '#/components/Dialog' import {useDialogControl} from '#/components/Dialog'
import {ArrowOutOfBox_Stroke2_Corner0_Rounded as ArrowOutOfBox} from '#/components/icons/ArrowOutOfBox' import {ArrowOutOfBox_Stroke2_Corner0_Rounded as ArrowOutOfBox} from '#/components/icons/ArrowOutOfBox'
import {QrCode_Stroke2_Corner0_Rounded as QrCode} from '#/components/icons/QrCode' import {QrCode_Stroke2_Corner0_Rounded as QrCode} from '#/components/icons/QrCode'
import {ListMaybePlaceholder} from '#/components/Lists'
import * as Menu from '#/components/Menu' import * as Menu from '#/components/Menu'
import {QrCodeDialog} from '#/components/StarterPack/QrCodeDialog' import {QrCodeDialog} from '#/components/StarterPack/QrCodeDialog'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
/** export function StarterPackScreen({
* TEMPORARY CONTENT, DO NOT TRANSLATE route,
*/ }: NativeStackScreenProps<CommonNavigatorParams, 'StarterPackLanding'>) {
/** const {name, rkey} = route.params
* TEMPORARY CONTENT, DO NOT TRANSLATE const {
*/ data: did,
/** isLoading: isLoadingDid,
* TEMPORARY CONTENT, DO NOT TRANSLATE isError: isErrorDid,
*/ } = useResolveDidQuery(name)
const {
data: starterPack,
isLoading: isLoadingStarterPack,
isError: isErrorStarterPack,
} = useStarterPackQuery({did, rkey})
const PLACEHOLDER_USERS = [ if (!did || !starterPack) {
{ return (
did: 'did:plc:qjeavhlw222ppsre4rscd3n2', <ListMaybePlaceholder
handle: 'test.handle', isLoading={isLoadingDid || isLoadingStarterPack}
displayName: 'Bossett', isError={isErrorDid || isErrorStarterPack}
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',
},
{ const items = [
did: 'did:plc:qjeavhlw222ppsre4rscd3n2', ...(starterPack.list ? ['People'] : []),
handle: 'test.handle', ...(starterPack.feeds ? ['Feeds'] : []),
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
return ( return (
<CenteredView style={[a.h_full_vh]}> <CenteredView style={[a.h_full_vh]}>
<StarterPackScreenInner /> <View style={isWeb ? {minHeight: '100%'} : {height: '100%'}}>
<PagerWithHeader
items={items}
isHeaderReady={true}
renderHeader={() => <Header starterPack={starterPack} />}>
{starterPack.list
? ({headerHeight, scrollElRef}) => (
<ProfilesList
key={0}
listUri={starterPack.list.uri}
headerHeight={headerHeight}
// @ts-expect-error
scrollElRef={scrollElRef}
/>
)
: null}
{starterPack.feeds
? ({headerHeight, scrollElRef}) => (
<FeedsList
key={1}
feeds={starterPack.feeds}
headerHeight={headerHeight}
// @ts-expect-error
scrollElRef={scrollElRef}
/>
)
: null}
</PagerWithHeader>
</View>
</CenteredView> </CenteredView>
) )
} }
function StarterPackScreenInner() { function Header({
const isOwn = true starterPack,
}: {
return ( starterPack: AppBskyGraphDefs.StarterPackView
<View style={isWeb ? {minHeight: '100%'} : {height: '100%'}}> }) {
<PagerWithHeader
items={['People', 'Feeds']}
isHeaderReady={true}
renderHeader={() => <Header isOwn={isOwn} />}>
{({headerHeight, scrollElRef}) => (
<ProfilesList
key={0}
profiles={PLACEHOLDER_USERS}
headerHeight={headerHeight}
// @ts-expect-error
scrollElRef={scrollElRef}
/>
)}
{({headerHeight, scrollElRef}) => (
<FeedsList
key={1}
feeds={PLACEHOLDER_FEEDS}
headerHeight={headerHeight}
// @ts-expect-error
scrollElRef={scrollElRef}
/>
)}
</PagerWithHeader>
</View>
)
}
function Header({isOwn}: {isOwn: boolean}) {
const {_} = useLingui() const {_} = useLingui()
const {currentAccount} = useSession()
const qrCodeDialogControl = useDialogControl() const qrCodeDialogControl = useDialogControl()
const {record, creator} = starterPack
const isOwn = creator.did === currentAccount?.did
if (!AppBskyGraphStarterpack.isRecord(record)) {
return null
}
return ( return (
<> <>
<ProfileSubpageHeader <ProfileSubpageHeader
isLoading={false} isLoading={false}
href="" href={makeProfileLink(creator)}
title="Science" title={record.name}
isOwner={false} isOwner={isOwn}
avatar={undefined} avatar={undefined}
creator={undefined} creator={creator}
avatarType="starter-pack"> avatarType="starter-pack">
<View style={[a.flex_row, a.gap_sm]}> <View style={[a.flex_row, a.gap_sm]}>
<Menu.Root> <Menu.Root>
@@ -218,10 +175,7 @@ function Header({isOwn}: {isOwn: boolean}) {
</View> </View>
</ProfileSubpageHeader> </ProfileSubpageHeader>
<View style={[a.px_md, a.py_lg]}> <View style={[a.px_md, a.py_lg]}>
<Text style={[a.text_md]}> <Text style={[a.text_md]}>{record.description}</Text>
(This is the description) A collection of feeds and users to get you
started with the science community on Bluesky!
</Text>
</View> </View>
<QrCodeDialog control={qrCodeDialogControl} url="https://bsky.app" /> <QrCodeDialog control={qrCodeDialogControl} url="https://bsky.app" />
+10 -8
View File
@@ -1,22 +1,24 @@
import {AppBskyGraphGetStarterPack} from '@atproto/api' import {StarterPackView} from '@atproto/api/dist/client/types/app/bsky/graph/defs'
import {useMutation} from '@tanstack/react-query' import {useMutation, useQuery} from '@tanstack/react-query'
import {useQuery} from 'react-query'
import {STALE} from 'state/queries/index' import {STALE} from 'state/queries/index'
import {useAgent, useSession} from 'state/session' import {useAgent, useSession} from 'state/session'
const RQKEY_ROOT = 'starter-pack' const RQKEY_ROOT = 'starter-pack'
export function useStarterPackQuery({id}: {id: string}) { export function useStarterPackQuery({did, rkey}: {did?: string; rkey: string}) {
const agent = useAgent() const agent = useAgent()
return useQuery<AppBskyGraphGetStarterPack.OutputSchema>({ const uri = `at://${did}/app.bsky.graph.starterpack/${rkey}`
queryKey: [RQKEY_ROOT, id],
return useQuery<StarterPackView>({
queryKey: [RQKEY_ROOT, did, rkey],
queryFn: async () => { queryFn: async () => {
const res = await agent.app.bsky.graph.getStarterPack({ 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, staleTime: STALE.MINUTES.FIVE,
}) })
} }