Drop the hard-coded what's hot algo

zio/stable
Paul Frazee 2023-05-18 15:12:18 -05:00
parent 2f4408582b
commit 84990c509e
6 changed files with 36 additions and 100 deletions

View File

@ -310,7 +310,7 @@ export class PostsFeedModel {
constructor(
public rootStore: RootStoreModel,
public feedType: 'home' | 'author' | 'suggested' | 'goodstuff' | 'custom',
public feedType: 'home' | 'author' | 'suggested' | 'custom',
params:
| GetTimeline.QueryParams
| GetAuthorFeed.QueryParams
@ -391,10 +391,9 @@ export class PostsFeedModel {
}
get feedTuners() {
if (this.feedType === 'goodstuff') {
if (this.feedType === 'custom') {
return [
FeedTuner.dedupReposts,
FeedTuner.likedRepliesOnly,
FeedTuner.preferredLangOnly(
this.rootStore.preferences.contentLanguages,
),
@ -701,15 +700,6 @@ export class PostsFeedModel {
return this.rootStore.agent.app.bsky.feed.getFeed(
params as GetCustomFeed.QueryParams,
)
} else if (this.feedType === 'goodstuff') {
const res = await getGoodStuff(
this.rootStore.session.currentSession?.accessJwt || '',
params as GetTimeline.QueryParams,
)
res.data.feed = (res.data.feed || []).filter(
item => !item.post.author.viewer?.muted,
)
return res
} else {
return this.rootStore.agent.getAuthorFeed(
params as GetAuthorFeed.QueryParams,
@ -717,45 +707,3 @@ export class PostsFeedModel {
}
}
}
// HACK
// temporary off-spec route to get the good stuff
// -prf
async function getGoodStuff(
accessJwt: string,
params: GetTimeline.QueryParams,
): Promise<GetTimeline.Response> {
const controller = new AbortController()
const to = setTimeout(() => controller.abort(), 15e3)
const uri = new URL('https://bsky.social/xrpc/app.bsky.unspecced.getPopular')
let k: keyof GetTimeline.QueryParams
for (k in params) {
if (typeof params[k] !== 'undefined') {
uri.searchParams.set(k, String(params[k]))
}
}
const res = await fetch(String(uri), {
method: 'get',
headers: {
accept: 'application/json',
authorization: `Bearer ${accessJwt}`,
},
signal: controller.signal,
})
const resHeaders: Record<string, string> = {}
res.headers.forEach((value: string, key: string) => {
resHeaders[key] = value
})
let resBody = await res.json()
clearTimeout(to)
return {
success: res.status === 200,
headers: resHeaders,
data: jsonToLex(resBody),
}
}

View File

@ -41,8 +41,8 @@ export function Component({}: {}) {
<View testID="contentLanguagesModal" style={[pal.view, styles.container]}>
<Text style={[pal.text, styles.title]}>Content Languages</Text>
<Text style={[pal.text, styles.description]}>
Which languages would you like to see in the What's Hot feed? (Leave
them all unchecked to see any language.)
Which languages would you like to see in the your feed? (Leave them all
unchecked to see any language.)
</Text>
<ScrollView style={styles.scrollContainer}>
{languages.map(lang => (

View File

@ -28,12 +28,7 @@ const FeedsTabBarDesktop = observer(
) => {
const store = useStores()
const items = useMemo(
() => [
'Following',
"What's hot",
...store.me.savedFeeds.pinnedFeedNames,
'My feeds',
],
() => ['Following', ...store.me.savedFeeds.pinnedFeedNames, 'My feeds'],
[store.me.savedFeeds.pinnedFeedNames],
)
const pal = usePalette('default')

View File

@ -33,12 +33,7 @@ export const FeedsTabBar = observer(
}, [store])
const items = useMemo(
() => [
'Following',
"What's hot",
...store.me.savedFeeds.pinnedFeedNames,
'My feeds',
],
() => ['Following', ...store.me.savedFeeds.pinnedFeedNames, 'My feeds'],
[store.me.savedFeeds.pinnedFeedNames],
)

View File

@ -1,5 +1,6 @@
import React from 'react'
import {StyleSheet, View} from 'react-native'
import {useNavigation} from '@react-navigation/native'
import {
FontAwesomeIcon,
FontAwesomeIconStyle,
@ -7,14 +8,21 @@ import {
import {Text} from '../util/text/Text'
import {Button} from '../util/forms/Button'
import {MagnifyingGlassIcon} from 'lib/icons'
import {NavigationProp} from 'lib/routes/types'
import {useStores} from 'state/index'
import {usePalette} from 'lib/hooks/usePalette'
import {s} from 'lib/styles'
export function WhatsHotEmptyState() {
export function CustomFeedEmptyState() {
const pal = usePalette('default')
const palInverted = usePalette('inverted')
const store = useStores()
const navigation = useNavigation<NavigationProp>()
const onPressFindAccounts = React.useCallback(() => {
navigation.navigate('SearchTab')
navigation.popToTop()
}, [navigation])
const onPressSettings = React.useCallback(() => {
store.shell.openModal({name: 'content-languages-settings'})
@ -26,9 +34,22 @@ export function WhatsHotEmptyState() {
<MagnifyingGlassIcon style={[styles.emptyIcon, pal.text]} size={62} />
</View>
<Text type="xl-medium" style={[s.textCenter, pal.text]}>
Your What's Hot feed is empty! This is because there aren't enough users
posting in your selected language.
This feed is empty! You may need to follow more users or tune your
language settings.
</Text>
<Button
type="inverted"
style={styles.emptyBtn}
onPress={onPressFindAccounts}>
<Text type="lg-medium" style={palInverted.text}>
Find accounts to follow
</Text>
<FontAwesomeIcon
icon="angle-right"
style={palInverted.text as FontAwesomeIconStyle}
size={14}
/>
</Button>
<Button type="inverted" style={styles.emptyBtn} onPress={onPressSettings}>
<Text type="lg-medium" style={palInverted.text}>
Update my settings

View File

@ -11,7 +11,7 @@ import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {useTabFocusEffect} from 'lib/hooks/useTabFocusEffect'
import {Feed} from '../com/posts/Feed'
import {FollowingEmptyState} from 'view/com/posts/FollowingEmptyState'
import {WhatsHotEmptyState} from 'view/com/posts/WhatsHotEmptyState'
import {CustomFeedEmptyState} from 'view/com/posts/CustomFeedEmptyState'
import {LoadLatestBtn} from '../com/util/load-latest/LoadLatestBtn'
import {FeedsTabBar} from '../com/pager/FeedsTabBar'
import {Pager, PagerRef, RenderTabBarFnProps} from 'view/com/pager/Pager'
@ -34,15 +34,6 @@ export const HomeScreen = withAuthRequired(
const pagerRef = React.useRef<PagerRef>(null)
const [selectedPage, setSelectedPage] = React.useState(0)
const [customFeeds, setCustomFeeds] = React.useState<PostsFeedModel[]>([])
const [initialLanguages] = React.useState(
store.preferences.contentLanguages,
)
const algoFeed: PostsFeedModel = React.useMemo(() => {
const feed = new PostsFeedModel(store, 'goodstuff', {})
feed.setup()
return feed
}, [store])
React.useEffect(() => {
const {pinned} = store.me.savedFeeds
@ -66,13 +57,6 @@ export const HomeScreen = withAuthRequired(
setCustomFeeds(feeds)
}, [store, store.me.savedFeeds.pinned, customFeeds, setCustomFeeds])
React.useEffect(() => {
// refresh whats hot when lang preferences change
if (initialLanguages !== store.preferences.contentLanguages) {
algoFeed.refresh()
}
}, [initialLanguages, store.preferences.contentLanguages, algoFeed])
useFocusEffect(
React.useCallback(() => {
store.shell.setMinimalShellMode(false)
@ -113,8 +97,8 @@ export const HomeScreen = withAuthRequired(
return <FollowingEmptyState />
}, [])
const renderWhatsHotEmptyState = React.useCallback(() => {
return <WhatsHotEmptyState />
const renderCustomFeedEmptyState = React.useCallback(() => {
return <CustomFeedEmptyState />
}, [])
const initialPage = store.me.followsCount === 0 ? 1 : 0
@ -133,26 +117,19 @@ export const HomeScreen = withAuthRequired(
feed={store.me.mainFeed}
renderEmptyState={renderFollowingEmptyState}
/>
<FeedPage
key="2"
testID="whatshotFeedPage"
isPageFocused={selectedPage === 1}
feed={algoFeed}
renderEmptyState={renderWhatsHotEmptyState}
/>
{customFeeds.map((f, index) => {
return (
<FeedPage
key={(f.params as GetCustomFeed.QueryParams).feed}
testID="customFeedPage"
isPageFocused={selectedPage === 2 + index}
isPageFocused={selectedPage === 1 + index}
feed={f}
renderEmptyState={renderFollowingEmptyState}
renderEmptyState={renderCustomFeedEmptyState}
/>
)
})}
<SavedFeeds
key={String(3 + store.me.savedFeeds.pinned.length)}
key={String(2 + store.me.savedFeeds.pinned.length)}
headerOffset={HEADER_OFFSET}
isPageFocused={selectedPage === 2 + store.me.savedFeeds.pinned.length}
/>