diff --git a/src/Navigation.tsx b/src/Navigation.tsx index f3a3d264f0..35bbc4386a 100644 --- a/src/Navigation.tsx +++ b/src/Navigation.tsx @@ -43,7 +43,8 @@ import {SavedFeeds} from 'view/screens/SavedFeeds' import HashtagScreen from '#/screens/Hashtag' import {ModerationScreen} from '#/screens/Moderation' import {ProfileLabelerLikedByScreen} from '#/screens/Profile/ProfileLabelerLikedBy' -import {Landing} from '#/screens/StarterPack/Landing' +import {LandingScreen} from '#/screens/StarterPack/Landing' +import {StarterPackScreen} from '#/screens/StarterPack/Main' import {Wizard} from '#/screens/StarterPack/Wizard' import {init as initAnalytics} from './lib/analytics/analytics' import {useWebScrollRestoration} from './lib/hooks/useWebScrollRestoration' @@ -308,9 +309,16 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) { getComponent={() => MessagesSettingsScreen} options={{title: title(msg`Chat settings`), requireAuth: true}} /> + StarterPackScreen} + options={{title: title(msg`Starter Pack`), requireAuth: true}} + /> Landing} + getComponent={() => LandingScreen} options={{title: title(msg`Join Bluesky Today!`)}} /> ) { const {_} = useLingui() const gate = useGate() const t = useTheme() - const {isTabletOrDesktop} = useWebMediaQueries() const setMinimalShellMode = useSetMinimalShellMode() const gradient = t.name === 'light' @@ -93,7 +91,14 @@ export function Landing({ }, []) React.useEffect(() => { + if (!gate('starter_packs_enabled')) { + // @ts-expect-error idk + navigation.replace('Home') + return + } + setMinimalShellMode(true) + return () => { setMinimalShellMode(false) } @@ -120,21 +125,22 @@ export function Landing({ - {/* TODO only display this when the total count is > 50 */} - 186 joined this week! + + 186 joined this week + - + (This is the description) A collection of feeds and users to get you started with the science community on Bluesky! @@ -162,7 +168,7 @@ export function Landing({ t.atoms.bg_contrast_25, a.rounded_sm, a.px_xs, - a.py_xl, + a.py_md, a.gap_xl, ]}> diff --git a/src/screens/StarterPack/Main/FeedsList.tsx b/src/screens/StarterPack/Main/FeedsList.tsx new file mode 100644 index 0000000000..78febf56a5 --- /dev/null +++ b/src/screens/StarterPack/Main/FeedsList.tsx @@ -0,0 +1,54 @@ +import React, {useCallback} from 'react' +import {View} from 'react-native' + +import {useBottomBarOffset} from 'lib/hooks/useBottomBarOffset' +import {isNative} from 'platform/detection' +import {FeedSourceCard} from 'view/com/feeds/FeedSourceCard' +import {List, ListRef} from 'view/com/util/List' +import {SectionRef} from '#/screens/Profile/Sections/types' + +function renderItem({item}: {item: string}) { + return +} + +function keyExtractor(item: string) { + return item +} + +interface ProfilesListProps { + feeds: string[] + headerHeight: number + scrollElRef: ListRef +} + +export const FeedsList = React.forwardRef( + function FeedsListImpl({feeds, headerHeight, scrollElRef}, ref) { + const [initialHeaderHeight] = React.useState(headerHeight) + const bottomBarOffset = useBottomBarOffset(20) + + const onScrollToTop = useCallback(() => { + scrollElRef.current?.scrollToOffset({ + animated: isNative, + offset: -headerHeight, + }) + }, [scrollElRef, headerHeight]) + + React.useImperativeHandle(ref, () => ({ + scrollToTop: onScrollToTop, + })) + + return ( + + } + showsVerticalScrollIndicator={false} + /> + ) + }, +) diff --git a/src/screens/StarterPack/Main/ProfilesList.tsx b/src/screens/StarterPack/Main/ProfilesList.tsx new file mode 100644 index 0000000000..50c49ede85 --- /dev/null +++ b/src/screens/StarterPack/Main/ProfilesList.tsx @@ -0,0 +1,55 @@ +import React, {useCallback} from 'react' +import {View} from 'react-native' +import {AppBskyActorDefs} from '@atproto/api' + +import {useBottomBarOffset} from 'lib/hooks/useBottomBarOffset' +import {isNative} from 'platform/detection' +import {ProfileCardWithFollowBtn} from 'view/com/profile/ProfileCard' +import {List, ListRef} from 'view/com/util/List' +import {SectionRef} from '#/screens/Profile/Sections/types' + +function renderItem({item}: {item: AppBskyActorDefs.ProfileViewBasic}) { + return +} + +function keyExtractor(item: AppBskyActorDefs.ProfileViewBasic, index: number) { + return `${item.did}-${index}` +} + +interface ProfilesListProps { + profiles: AppBskyActorDefs.ProfileViewBasic[] + headerHeight: number + scrollElRef: ListRef +} + +export const ProfilesList = React.forwardRef( + function ProfilesListImpl({profiles, headerHeight, scrollElRef}, ref) { + const [initialHeaderHeight] = React.useState(headerHeight) + const bottomBarOffset = useBottomBarOffset(20) + + const onScrollToTop = useCallback(() => { + scrollElRef.current?.scrollToOffset({ + animated: isNative, + offset: -headerHeight, + }) + }, [scrollElRef, headerHeight]) + + React.useImperativeHandle(ref, () => ({ + scrollToTop: onScrollToTop, + })) + + return ( + + } + showsVerticalScrollIndicator={false} + /> + ) + }, +) diff --git a/src/screens/StarterPack/Main/index.tsx b/src/screens/StarterPack/Main/index.tsx new file mode 100644 index 0000000000..1bb4fa11f4 --- /dev/null +++ b/src/screens/StarterPack/Main/index.tsx @@ -0,0 +1,183 @@ +import React from 'react' +import {Text, View} from 'react-native' +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 {isWeb} from 'platform/detection' +import {PagerWithHeader} from 'view/com/pager/PagerWithHeader' +import {ProfileSubpageHeader} from 'view/com/profile/ProfileSubpageHeader' +import {CenteredView} from 'view/com/util/Views' +import {FeedsList} from '#/screens/StarterPack/Main/FeedsList' +import {ProfilesList} from '#/screens/StarterPack/Main/ProfilesList' +import {atoms as a} from '#/alf' +import {Button, ButtonText} from '#/components/Button' + +/** + * TEMPORARY CONTENT, DO NOT TRANSLATE + */ +/** + * TEMPORARY CONTENT, DO NOT TRANSLATE + */ +/** + * TEMPORARY CONTENT, DO NOT TRANSLATE + */ + +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', + }, + { + did: 'did:plc:qjeavhlw222ppsre4rscd3n2', + handle: 'test.handle', + displayName: 'hailey', + avatar: + 'https://cdn.bsky.app/img/avatar/plain/did:plc:oisofpd7lj26yvgiivf3lxsi/bafkreia4lpswywb5yx3gsezqb5io73kt7icw634ks4m4mmbfvp7e62cxku@jpeg', + }, + { + did: 'did:plc:qjeavhlw222ppsre4rscd3n2', + handle: 'test.handle', + displayName: 'samuel', + avatar: + 'https://cdn.bsky.app/img/avatar/plain/did:plc:p2cp5gopk7mgjegy6wadk3ep/bafkreias5vktko4jpg4mwp4audptcbdfkb4o3cfyzt4426mj2h7ewwvg7q@jpeg', + }, + + { + did: 'did:plc:qjeavhlw222ppsre4rscd3n2', + handle: 'test.handle', + displayName: 'Paul “Frazee” 🦋', + avatar: + 'https://cdn.bsky.app/img/avatar/plain/did:plc:ragtjsm2j2vknwkz3zp4oxrd/bafkreihhpqdyntku66himwor5wlhtdo44hllmngj2ofmbqnm25bdm454wq@jpeg', + }, + { + 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 ( + + + + ) +} + +function StarterPackScreenInner() { + const isOwn = true + + return ( + +
}> + {({headerHeight, scrollElRef}) => ( + + )} + {({headerHeight, scrollElRef}) => ( + + )} + + + ) +} + +function Header({isOwn}: {isOwn: boolean}) { + const {_} = useLingui() + + return ( + <> + + + + {isOwn && ( + + )} + + + + + (This is the description) A collection of feeds and users to get you + started with the science community on Bluesky! + + + + ) +} diff --git a/src/view/com/profile/ProfileSubpageHeader.tsx b/src/view/com/profile/ProfileSubpageHeader.tsx index 549fc5151a..3a3cd89843 100644 --- a/src/view/com/profile/ProfileSubpageHeader.tsx +++ b/src/view/com/profile/ProfileSubpageHeader.tsx @@ -21,6 +21,7 @@ import {Text} from '../util/text/Text' import {UserAvatar, UserAvatarType} from '../util/UserAvatar' import {CenteredView} from '../util/Views' import hairlineWidth = StyleSheet.hairlineWidth +import {StarterPackIcon} from '#/components/icons/StarterPackIcon' export function ProfileSubpageHeader({ isLoading, @@ -43,7 +44,7 @@ export function ProfileSubpageHeader({ handle: string } | undefined - avatarType: UserAvatarType + avatarType: UserAvatarType | 'starter-pack' }>) { const setDrawerOpen = useSetDrawerOpen() const navigation = useNavigation() @@ -130,7 +131,11 @@ export function ProfileSubpageHeader({ accessibilityLabel={_(msg`View the avatar`)} accessibilityHint="" style={{width: 58}}> - + {avatarType === 'starter-pack' ? ( + + ) : ( + + )} {isLoading ? ( diff --git a/src/view/screens/Settings/index.tsx b/src/view/screens/Settings/index.tsx index 48727a98b4..ed660c94f3 100644 --- a/src/view/screens/Settings/index.tsx +++ b/src/view/screens/Settings/index.tsx @@ -854,6 +854,28 @@ export function SettingsScreen({}: Props) { Reset preferences state + onPressDeleteChatDeclaration()} + accessibilityRole="button" + accessibilityLabel={_(msg`Delete chat declaration record`)} + accessibilityHint={_(msg`Deletes the chat declaration record`)}> + + Delete chat declaration record + + + { + navigation.navigate('StarterPack', {id: '123'}) + }} + accessibilityRole="button" + accessibilityLabel={_(msg`Navigate to Starter Pack`)} + accessibilityHint={_(msg`Navigate to Starter Pack`)}> + + Navigate to Starter Pack + + { @@ -866,16 +888,6 @@ export function SettingsScreen({}: Props) { Navigate to Starter Pack Landing - onPressDeleteChatDeclaration()} - accessibilityRole="button" - accessibilityLabel={_(msg`Delete chat declaration record`)} - accessibilityHint={_(msg`Deletes the chat declaration record`)}> - - Delete chat declaration record - -