diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/api/feed/home.ts | 88 | ||||
-rw-r--r-- | src/lib/api/feed/merge.ts | 2 | ||||
-rw-r--r-- | src/state/queries/post-feed.ts | 7 | ||||
-rw-r--r-- | src/view/com/modals/DeleteAccount.tsx | 7 | ||||
-rw-r--r-- | src/view/com/posts/DiscoverFallbackHeader.tsx | 43 | ||||
-rw-r--r-- | src/view/com/posts/Feed.tsx | 8 | ||||
-rw-r--r-- | src/view/screens/Home.tsx | 3 |
7 files changed, 152 insertions, 6 deletions
diff --git a/src/lib/api/feed/home.ts b/src/lib/api/feed/home.ts new file mode 100644 index 000000000..91634927a --- /dev/null +++ b/src/lib/api/feed/home.ts @@ -0,0 +1,88 @@ +import {AppBskyFeedDefs} from '@atproto/api' +import {FeedAPI, FeedAPIResponse} from './types' +import {FollowingFeedAPI} from './following' +import {CustomFeedAPI} from './custom' +import {PROD_DEFAULT_FEED} from '#/lib/constants' + +// HACK +// the feed API does not include any facilities for passing down +// non-post elements. adding that is a bit of a heavy lift, and we +// have just one temporary usecase for it: flagging when the home feed +// falls back to discover. +// we use this fallback marker post to drive this instead. see Feed.tsx +// for the usage. +// -prf +export const FALLBACK_MARKER_POST: AppBskyFeedDefs.FeedViewPost = { + post: { + uri: 'fallback-marker-post', + cid: 'fake', + record: {}, + author: { + did: 'did:fake', + handle: 'fake.com', + }, + indexedAt: new Date().toISOString(), + }, +} + +export class HomeFeedAPI implements FeedAPI { + following: FollowingFeedAPI + discover: CustomFeedAPI + usingDiscover = false + itemCursor = 0 + + constructor() { + this.following = new FollowingFeedAPI() + this.discover = new CustomFeedAPI({feed: PROD_DEFAULT_FEED('whats-hot')}) + } + + reset() { + this.following = new FollowingFeedAPI() + this.discover = new CustomFeedAPI({feed: PROD_DEFAULT_FEED('whats-hot')}) + this.usingDiscover = false + this.itemCursor = 0 + } + + async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> { + if (this.usingDiscover) { + return this.discover.peekLatest() + } + return this.following.peekLatest() + } + + async fetch({ + cursor, + limit, + }: { + cursor: string | undefined + limit: number + }): Promise<FeedAPIResponse> { + if (!cursor) { + this.reset() + } + + let returnCursor + let posts: AppBskyFeedDefs.FeedViewPost[] = [] + + if (!this.usingDiscover) { + const res = await this.following.fetch({cursor, limit}) + returnCursor = res.cursor + posts = posts.concat(res.feed) + if (res.feed.length === 0 || !cursor) { + posts.push(FALLBACK_MARKER_POST) + this.usingDiscover = true + } + } + + if (this.usingDiscover) { + const res = await this.discover.fetch({cursor, limit}) + returnCursor = res.cursor + posts = posts.concat(res.feed) + } + + return { + cursor: returnCursor, + feed: posts, + } + } +} diff --git a/src/lib/api/feed/merge.ts b/src/lib/api/feed/merge.ts index 2fef9db87..28bf143cb 100644 --- a/src/lib/api/feed/merge.ts +++ b/src/lib/api/feed/merge.ts @@ -26,7 +26,7 @@ export class MergeFeedAPI implements FeedAPI { reset() { this.following = new MergeFeedSource_Following(this.feedTuners) - this.customFeeds = [] // just empty the array, they will be captured in _fetchNext() + this.customFeeds = [] this.feedCursor = 0 this.itemCursor = 0 this.sampleCursor = 0 diff --git a/src/state/queries/post-feed.ts b/src/state/queries/post-feed.ts index dbb729133..82acf3974 100644 --- a/src/state/queries/post-feed.ts +++ b/src/state/queries/post-feed.ts @@ -18,6 +18,7 @@ import {LikesFeedAPI} from 'lib/api/feed/likes' import {CustomFeedAPI} from 'lib/api/feed/custom' import {ListFeedAPI} from 'lib/api/feed/list' import {MergeFeedAPI} from 'lib/api/feed/merge' +import {HomeFeedAPI} from '#/lib/api/feed/home' import {logger} from '#/logger' import {STALE} from '#/state/queries' import {precacheFeedPosts as precacheResolvedUris} from './resolve-uri' @@ -338,7 +339,11 @@ function createApi( feedTuners: FeedTunerFn[], ) { if (feedDesc === 'home') { - return new MergeFeedAPI(params, feedTuners) + if (params.mergeFeedEnabled) { + return new MergeFeedAPI(params, feedTuners) + } else { + return new HomeFeedAPI() + } } else if (feedDesc === 'following') { return new FollowingFeedAPI() } else if (feedDesc.startsWith('author')) { diff --git a/src/view/com/modals/DeleteAccount.tsx b/src/view/com/modals/DeleteAccount.tsx index 0cfc098d4..945d7bc89 100644 --- a/src/view/com/modals/DeleteAccount.tsx +++ b/src/view/com/modals/DeleteAccount.tsx @@ -160,7 +160,7 @@ export function Component({}: {}) { {/* TODO: Update this label to be more concise */} <Text type="lg" - style={styles.description} + style={[pal.text, styles.description]} nativeID="confirmationCode"> <Trans> Check your inbox for an email with the confirmation code to @@ -180,7 +180,10 @@ export function Component({}: {}) { msg`Input confirmation code for account deletion`, )} /> - <Text type="lg" style={styles.description} nativeID="password"> + <Text + type="lg" + style={[pal.text, styles.description]} + nativeID="password"> <Trans>Please enter your password as well:</Trans> </Text> <TextInput diff --git a/src/view/com/posts/DiscoverFallbackHeader.tsx b/src/view/com/posts/DiscoverFallbackHeader.tsx new file mode 100644 index 000000000..dcfa3b012 --- /dev/null +++ b/src/view/com/posts/DiscoverFallbackHeader.tsx @@ -0,0 +1,43 @@ +import React from 'react' +import {View} from 'react-native' +import {Trans} from '@lingui/macro' +import {Text} from '../util/text/Text' +import {usePalette} from '#/lib/hooks/usePalette' +import {TextLink} from '../util/Link' +import {InfoCircleIcon} from '#/lib/icons' + +export function DiscoverFallbackHeader() { + const pal = usePalette('default') + return ( + <View + style={[ + { + flexDirection: 'row', + alignItems: 'center', + paddingVertical: 12, + paddingHorizontal: 12, + borderTopWidth: 1, + }, + pal.border, + pal.viewLight, + ]}> + <View style={{width: 68, paddingLeft: 12}}> + <InfoCircleIcon size={36} style={pal.textLight} strokeWidth={1.5} /> + </View> + <View style={{flex: 1}}> + <Text type="md" style={pal.text}> + <Trans> + We ran out of posts from your follows. Here's the latest from + </Trans>{' '} + <TextLink + type="md-medium" + href="/profile/bsky.app/feed/whats-hot" + text="Discover" + style={pal.link} + /> + . + </Text> + </View> + </View> + ) +} diff --git a/src/view/com/posts/Feed.tsx b/src/view/com/posts/Feed.tsx index cd9f26463..04753fe6c 100644 --- a/src/view/com/posts/Feed.tsx +++ b/src/view/com/posts/Feed.tsx @@ -30,6 +30,8 @@ import {useSession} from '#/state/session' import {STALE} from '#/state/queries' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' +import {DiscoverFallbackHeader} from './DiscoverFallbackHeader' +import {FALLBACK_MARKER_POST} from '#/lib/api/feed/home' const LOADING_ITEM = {_reactKey: '__loading__'} const EMPTY_FEED_ITEM = {_reactKey: '__empty__'} @@ -265,6 +267,12 @@ let Feed = ({ ) } else if (item === LOADING_ITEM) { return <PostFeedLoadingPlaceholder /> + } else if (item.rootUri === FALLBACK_MARKER_POST.post.uri) { + // HACK + // tell the user we fell back to discover + // see home.ts (feed api) for more info + // -prf + return <DiscoverFallbackHeader /> } return <FeedSlice slice={item} /> }, diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx index 0e20a9cf7..7d6a40f02 100644 --- a/src/view/screens/Home.tsx +++ b/src/view/screens/Home.tsx @@ -19,7 +19,6 @@ import {useSession} from '#/state/session' import {loadString, saveString} from '#/lib/storage' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' import {clamp} from '#/lib/numbers' -import {PROD_DEFAULT_FEED} from '#/lib/constants' type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'> export function HomeScreen(props: Props) { @@ -112,7 +111,7 @@ function HomeScreenReady({ mergeFeedEnabled: Boolean(preferences.feedViewPrefs.lab_mergeFeedEnabled), mergeFeedSources: preferences.feedViewPrefs.lab_mergeFeedEnabled ? preferences.feeds.saved - : [PROD_DEFAULT_FEED('whats-hot')], + : [], } }, [preferences]) |