handle following and pinning feeds, acocunt createdAt

This commit is contained in:
Hailey
2024-06-10 00:41:03 -07:00
parent d2bdcc4c99
commit 6f188b0eb2
8 changed files with 98 additions and 43 deletions
-2
View File
@@ -39,7 +39,6 @@ import {ToastContainer} from 'view/com/util/Toast.web'
import {Shell} from 'view/shell/index' import {Shell} from 'view/shell/index'
import {ThemeProvider as Alf} from '#/alf' import {ThemeProvider as Alf} from '#/alf'
import {useColorModeTheme} from '#/alf/util/useColorModeTheme' import {useColorModeTheme} from '#/alf/util/useColorModeTheme'
import {useStarterPackEntry} from '#/components/hooks/useStarterPackEntry'
import {Provider as PortalProvider} from '#/components/Portal' import {Provider as PortalProvider} from '#/components/Portal'
import {BackgroundNotificationPreferencesProvider} from '../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider' import {BackgroundNotificationPreferencesProvider} from '../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider'
import I18nProvider from './locale/i18nProvider' import I18nProvider from './locale/i18nProvider'
@@ -52,7 +51,6 @@ function InnerApp() {
const theme = useColorModeTheme() const theme = useColorModeTheme()
const {_} = useLingui() const {_} = useLingui()
useIntentHandler() useIntentHandler()
useStarterPackEntry()
// init // init
useEffect(() => { useEffect(() => {
@@ -1,15 +0,0 @@
import React from 'react'
import {useSetStarterPack} from 'state/preferences/starter-pack'
export function useStarterPackEntry() {
const setStarterPack = useSetStarterPack()
React.useEffect(() => {
const url = new URL(window.location.href)
const pathParts = url.pathname.split('/')
if (pathParts[0] === 'start' && pathParts.length === 2) {
setStarterPack(pathParts[1])
}
}, [setStarterPack])
}
+57 -4
View File
@@ -1,5 +1,6 @@
import React from 'react' import React from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import {AppBskyGraphDefs, AtUri} 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 {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
@@ -14,6 +15,10 @@ import {useAgent} from '#/state/session'
import {useOnboardingDispatch} from '#/state/shell' import {useOnboardingDispatch} from '#/state/shell'
import {uploadBlob} from 'lib/api' import {uploadBlob} from 'lib/api'
import {useRequestNotificationsPermission} from 'lib/notifications/notifications' import {useRequestNotificationsPermission} from 'lib/notifications/notifications'
import {
useSetUsedStarterPack,
useUsedStarterPack,
} from 'state/preferences/starter-pack'
import { import {
DescriptionText, DescriptionText,
OnboardingControls, OnboardingControls,
@@ -41,15 +46,49 @@ export function StepFinished() {
const queryClient = useQueryClient() const queryClient = useQueryClient()
const agent = useAgent() const agent = useAgent()
const requestNotificationsPermission = useRequestNotificationsPermission() const requestNotificationsPermission = useRequestNotificationsPermission()
const usedStarterPack = useUsedStarterPack()
const setUsedStarterPack = useSetUsedStarterPack()
const finishOnboarding = React.useCallback(async () => { const finishOnboarding = React.useCallback(async () => {
setSaving(true) setSaving(true)
const {interestsStepResults, profileStepResults} = state
const {selectedInterests} = interestsStepResults
try { try {
let starterPack: AppBskyGraphDefs.StarterPackView | undefined
let listItems: AppBskyGraphDefs.ListItemView[] | undefined
if (usedStarterPack) {
const spRes = await agent.app.bsky.graph.getStarterPack({
starterPack: usedStarterPack.uri,
})
starterPack = spRes.data.starterPack
if (starterPack.list) {
const listRes = await agent.app.bsky.graph.getList({
list: starterPack.list.uri,
limit: 51,
})
listItems = listRes.data.items
}
}
const {interestsStepResults, profileStepResults} = state
const {selectedInterests} = interestsStepResults
await Promise.all([ await Promise.all([
bulkWriteFollows(agent, [BSKY_APP_ACCOUNT_DID]), bulkWriteFollows(agent, [
BSKY_APP_ACCOUNT_DID,
...(listItems?.map(i => i.subject.did) ?? []),
]),
(async () => {
if (starterPack?.feeds?.length) {
await agent.addSavedFeeds(
starterPack.feeds.map(f => ({
type: 'feed',
value: f.uri,
pinned: true,
id: new AtUri(f.uri).rkey,
})),
)
}
})(),
(async () => { (async () => {
await agent.setInterestsPref({tags: selectedInterests}) await agent.setInterestsPref({tags: selectedInterests})
})(), })(),
@@ -63,9 +102,20 @@ export function StepFinished() {
if (res.data.blob) { if (res.data.blob) {
existing.avatar = res.data.blob existing.avatar = res.data.blob
} }
existing.createdAt = new Date().toISOString()
if (starterPack) {
existing.joinedViaStarterPack = {
uri: starterPack.uri,
cid: starterPack.cid,
}
}
return existing return existing
}) })
} }
logEvent('onboarding:finished:avatarResult', { logEvent('onboarding:finished:avatarResult', {
avatarResult: profileStepResults.isCreatedAvatar avatarResult: profileStepResults.isCreatedAvatar
? 'created' ? 'created'
@@ -96,6 +146,7 @@ export function StepFinished() {
}) })
setSaving(false) setSaving(false)
setUsedStarterPack(undefined)
dispatch({type: 'finish'}) dispatch({type: 'finish'})
onboardDispatch({type: 'finish'}) onboardDispatch({type: 'finish'})
track('OnboardingV2:StepFinished:End') track('OnboardingV2:StepFinished:End')
@@ -105,10 +156,12 @@ export function StepFinished() {
state, state,
queryClient, queryClient,
agent, agent,
setUsedStarterPack,
dispatch, dispatch,
onboardDispatch, onboardDispatch,
track, track,
requestNotificationsPermission, requestNotificationsPermission,
usedStarterPack,
]) ])
React.useEffect(() => { React.useEffect(() => {
+23 -7
View File
@@ -8,10 +8,13 @@ import {
} from '@atproto/api' } 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 {useNavigation} from '@react-navigation/native'
import {CommonNavigatorParams} from 'lib/routes/types' import {NavigationProp} from 'lib/routes/types'
import {useSetUsedStarterPack} from 'state/preferences/starter-pack'
import {useSession} from 'state/session'
import {useSetMinimalShellMode} from 'state/shell' import {useSetMinimalShellMode} from 'state/shell'
import {useLoggedOutViewControls} from 'state/shell/logged-out'
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'
import {CenteredView} from 'view/com/util/Views' import {CenteredView} from 'view/com/util/Views'
@@ -116,10 +119,10 @@ const mockSP = {
], ],
} }
export function LandingScreen({ export function LandingScreen({}) {
navigation,
}: NativeStackScreenProps<CommonNavigatorParams, 'StarterPackLanding'>) {
// const {name, rkey} = route.params // const {name, rkey} = route.params
const navigation = useNavigation<NavigationProp>()
const {currentAccount} = useSession()
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
// const { // const {
@@ -134,11 +137,16 @@ export function LandingScreen({
// } = useStarterPackQuery({did, rkey}) // } = useStarterPackQuery({did, rkey})
React.useEffect(() => { React.useEffect(() => {
if (currentAccount) {
navigation.navigate('Home')
return
}
setMinimalShellMode(true) setMinimalShellMode(true)
return () => { return () => {
setMinimalShellMode(false) setMinimalShellMode(false)
} }
}, [navigation, setMinimalShellMode]) }, [currentAccount, navigation, setMinimalShellMode])
// if (!did || !starterPack) { // if (!did || !starterPack) {
// return ( // return (
@@ -160,6 +168,8 @@ function LandingScreenInner({
const {record, creator, listItemsSample, feeds, joinedWeekCount} = starterPack const {record, creator, listItemsSample, feeds, joinedWeekCount} = starterPack
const {_} = useLingui() const {_} = useLingui()
const t = useTheme() const t = useTheme()
const {requestSwitchToAccount} = useLoggedOutViewControls()
const setUsedStarterPack = useSetUsedStarterPack()
const gradient = const gradient =
t.name === 'light' t.name === 'light'
@@ -205,7 +215,13 @@ function LandingScreenInner({
)} )}
<Button <Button
label={_(msg`Join Bluesky now`)} label={_(msg`Join Bluesky now`)}
onPress={() => {}} onPress={() => {
setUsedStarterPack({
uri: starterPack.uri,
cid: starterPack.cid,
})
requestSwitchToAccount({requestedAccount: 'new'})
}}
variant="solid" variant="solid"
color="primary" color="primary"
size="large"> size="large">
+1 -3
View File
@@ -25,9 +25,7 @@ export function StepFeeds() {
const [state, dispatch] = useWizardState() const [state, dispatch] = useWizardState()
const [query, setQuery] = useState('') const [query, setQuery] = useState('')
const {data: popularFeedsPages, fetchNextPage} = useGetPopularFeedsQuery({ const {data: popularFeedsPages, fetchNextPage} = useGetPopularFeedsQuery(30)
limit: 30,
})
const popularFeeds = const popularFeeds =
popularFeedsPages?.pages.flatMap(page => page.feeds) || [] popularFeedsPages?.pages.flatMap(page => page.feeds) || []
+7 -2
View File
@@ -88,7 +88,12 @@ export const schema = z.object({
disableHaptics: z.boolean().optional(), disableHaptics: z.boolean().optional(),
disableAutoplay: z.boolean().optional(), disableAutoplay: z.boolean().optional(),
kawaii: z.boolean().optional(), kawaii: z.boolean().optional(),
starterPackId: z.string().optional(), usedStarterPack: z
.object({
uri: z.string(),
cid: z.string(),
})
.optional(),
}) })
export type Schema = z.infer<typeof schema> export type Schema = z.infer<typeof schema>
@@ -127,5 +132,5 @@ export const defaults: Schema = {
disableHaptics: false, disableHaptics: false,
disableAutoplay: prefersReducedMotion, disableAutoplay: prefersReducedMotion,
kawaii: false, kawaii: false,
starterPackId: undefined, usedStarterPack: undefined,
} }
+9 -9
View File
@@ -2,23 +2,23 @@ import React from 'react'
import * as persisted from '#/state/persisted' import * as persisted from '#/state/persisted'
type StateContext = string | undefined type StateContext = {uri: string; cid: string} | undefined
type SetContext = (v: string) => void type SetContext = (v: StateContext) => void
const stateContext = React.createContext<StateContext>(undefined) const stateContext = React.createContext<StateContext>(undefined)
const setContext = React.createContext<SetContext>((_: string) => {}) const setContext = React.createContext<SetContext>((_: StateContext) => {})
export function Provider({children}: {children: React.ReactNode}) { export function Provider({children}: {children: React.ReactNode}) {
const [state, setState] = React.useState<string>() const [state, setState] = React.useState<StateContext>()
const setStateWrapped = (v: string) => { const setStateWrapped = (v: StateContext) => {
setState(v) setState(v)
persisted.write('starterPackId', v) persisted.write('usedStarterPack', v)
} }
React.useEffect(() => { React.useEffect(() => {
return persisted.onUpdate(() => { return persisted.onUpdate(() => {
setState(persisted.get('starterPackId')) setState(persisted.get('usedStarterPack'))
}) })
}, []) }, [])
@@ -31,5 +31,5 @@ export function Provider({children}: {children: React.ReactNode}) {
) )
} }
export const useStarterPack = () => React.useContext(stateContext) export const useUsedStarterPack = () => React.useContext(stateContext)
export const useSetStarterPack = () => React.useContext(setContext) export const useSetUsedStarterPack = () => React.useContext(setContext)
+1 -1
View File
@@ -173,7 +173,7 @@ export function useFeedSourceInfoQuery({uri}: {uri: string}) {
export const useGetPopularFeedsQueryKey = ['getPopularFeeds'] export const useGetPopularFeedsQueryKey = ['getPopularFeeds']
export function useGetPopularFeedsQuery({limit = 10}: {limit?: number}) { export function useGetPopularFeedsQuery(limit: number = 10) {
const agent = useAgent() const agent = useAgent()
return useInfiniteQuery< return useInfiniteQuery<
AppBskyUnspeccedGetPopularFeedGenerators.OutputSchema, AppBskyUnspeccedGetPopularFeedGenerators.OutputSchema,