Handle no pinned feeds
This commit is contained in:
@@ -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,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user