Handle no pinned feeds

This commit is contained in:
Eric Bailey
2024-04-23 15:49:53 -05:00
parent b0e394c42e
commit 112796a997
3 changed files with 149 additions and 33 deletions
+17
View File
@@ -1,4 +1,6 @@
import {Insets, Platform} from 'react-native'
import {AppBskyActorDefs} from '@atproto/api'
import {TID} from '@atproto/common-web'
export const LOCAL_DEV_SERVICE =
Platform.OS === 'android' ? 'http://10.0.2.2:2583' : 'http://localhost:2583'
@@ -92,3 +94,18 @@ export const BSKY_FEED_OWNER_DIDS = [
export const DISCOVER_FEED_URI =
'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot'
export const RECOMMENDED_SAVED_FEEDS: AppBskyActorDefs.SavedFeed[] = [
{
id: TID.nextStr(),
type: 'feed',
value: DISCOVER_FEED_URI,
pinned: true,
},
{
id: TID.nextStr(),
type: 'timeline',
value: 'home',
pinned: true,
},
]
+89
View File
@@ -0,0 +1,89 @@
import React from 'react'
import {useWindowDimensions, View} from 'react-native'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {RECOMMENDED_SAVED_FEEDS} from '#/lib/constants'
import {useSetSaveFeedsMutation} from '#/state/queries/preferences'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {CenteredView} from '#/view/com/util/Views'
import {atoms as a} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import {ListSparkle_Stroke2_Corner0_Rounded as ListSparkle} from '#/components/icons/ListSparkle'
import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus'
import {Link} from '#/components/Link'
import {Text} from '#/components/Typography'
export function useHeaderOffset() {
const {isDesktop, isTablet} = useWebMediaQueries()
const {fontScale} = useWindowDimensions()
if (isDesktop || isTablet) {
return 0
}
const navBarHeight = 42
const tabBarPad = 10 + 10 + 3 // padding + border
const normalLineHeight = 1.2
const tabBarText = 16 * normalLineHeight * fontScale
return navBarHeight + tabBarPad + tabBarText
}
export function NoFeedsPinned() {
const {_} = useLingui()
const headerOffset = useHeaderOffset()
const {isPending, mutateAsync: setSavedFeeds} = useSetSaveFeedsMutation()
const addRecommendedFeeds = React.useCallback(async () => {
await setSavedFeeds(RECOMMENDED_SAVED_FEEDS)
}, [setSavedFeeds])
return (
<CenteredView sideBorders style={[a.h_full_vh]}>
<View
style={[
a.align_center,
a.h_full_vh,
a.py_3xl,
a.px_xl,
{
paddingTop: headerOffset + a.py_3xl.paddingTop,
},
]}>
<View style={[a.align_center, a.gap_sm, a.pb_xl]}>
<Text style={[a.text_xl, a.font_bold]}>
<Trans>Whoops!</Trans>
</Text>
<Text
style={[a.text_md, a.text_center, a.leading_snug, {maxWidth: 340}]}>
<Trans>
Looks like you unpinned all your feeds. But don't worry, you can
add some below 😄
</Trans>
</Text>
</View>
<View style={[a.flex_row, a.gap_md, a.justify_center, a.flex_wrap]}>
<Button
disabled={isPending}
label={_(msg`Apply default recommended feeds`)}
size="medium"
variant="solid"
color="primary"
onPress={addRecommendedFeeds}>
<ButtonIcon icon={Plus} position="left" />
<ButtonText>{_(msg`Add recommended feeds`)}</ButtonText>
</Button>
<Link
label={_(msg`Browse other feeds`)}
to="/feeds"
size="medium"
variant="solid"
color="secondary">
<ButtonIcon icon={ListSparkle} position="left" />
<ButtonText>{_(msg`Browse other feeds`)}</ButtonText>
</Link>
</View>
</View>
</CenteredView>
)
}
+43 -33
View File
@@ -21,6 +21,7 @@ import {Pager, PagerRef, RenderTabBarFnProps} from 'view/com/pager/Pager'
import {CustomFeedEmptyState} from 'view/com/posts/CustomFeedEmptyState'
import {FollowingEmptyState} from 'view/com/posts/FollowingEmptyState'
import {FollowingEndOfFeed} from 'view/com/posts/FollowingEndOfFeed'
import {NoFeedsPinned} from '#/screens/Home/NoFeedsPinned'
import {HomeHeader} from '../com/home/HomeHeader'
type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'>
@@ -110,12 +111,14 @@ function HomeScreenReady({
useFocusEffect(
useNonReactiveCallback(() => {
logEvent('home:feedDisplayed', {
index: selectedIndex,
feedType: selectedFeed.split('|')[0],
feedUrl: selectedFeed,
reason: 'focus',
})
if (selectedFeed) {
logEvent('home:feedDisplayed', {
index: selectedIndex,
feedType: selectedFeed.split('|')[0],
feedUrl: selectedFeed,
reason: 'focus',
})
}
}),
)
@@ -147,12 +150,15 @@ function HomeScreenReady({
const onPageSelecting = React.useCallback(
(index: number, reason: LogEvents['home:feedDisplayed']['reason']) => {
const feed = allFeeds[index]
logEvent('home:feedDisplayed', {
index,
feedType: feed.split('|')[0],
feedUrl: feed,
reason,
})
if (feed) {
logEvent('home:feedDisplayed', {
index,
feedType: feed.split('|')[0],
feedUrl: feed,
reason,
})
}
},
[allFeeds],
)
@@ -212,35 +218,39 @@ function HomeScreenReady({
onPageSelected={onPageSelected}
onPageScrollStateChanged={onPageScrollStateChanged}
renderTabBar={renderTabBar}>
{allFeeds.map(feed => {
if (feed === 'home' || feed === 'following') {
{allFeeds.length ? (
allFeeds.map(feed => {
if (feed === 'home' || feed === 'following') {
return (
<FeedPage
key={feed}
testID="followingFeedPage"
isPageFocused={selectedFeed === feed}
feed={feed}
feedParams={homeFeedParams}
renderEmptyState={renderFollowingEmptyState}
renderEndOfFeed={FollowingEndOfFeed}
/>
)
}
const savedFeedConfig = preferences.savedFeeds.find(f => {
return feed.includes(f.value)
})
return (
<FeedPage
key={feed}
testID="followingFeedPage"
testID="customFeedPage"
isPageFocused={selectedFeed === feed}
feed={feed}
feedParams={homeFeedParams}
renderEmptyState={renderFollowingEmptyState}
renderEndOfFeed={FollowingEndOfFeed}
renderEmptyState={renderCustomFeedEmptyState}
savedFeedConfig={savedFeedConfig}
/>
)
}
const savedFeedConfig = preferences.savedFeeds.find(f => {
return feed.includes(f.value)
})
return (
<FeedPage
key={feed}
testID="customFeedPage"
isPageFocused={selectedFeed === feed}
feed={feed}
renderEmptyState={renderCustomFeedEmptyState}
savedFeedConfig={savedFeedConfig}
/>
)
})}
) : (
<NoFeedsPinned />
)}
</Pager>
) : (
<Pager