Add shutdown message to for you feed (#3776)

zio/stable
Paul Frazee 2024-05-10 21:57:21 -07:00 committed by GitHub
parent d0440d087e
commit 6f5b551bda
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 174 additions and 2 deletions

View File

@ -111,6 +111,10 @@ export const RECOMMENDED_SAVED_FEEDS: Pick<
'type' | 'value' | 'pinned' 'type' | 'value' | 'pinned'
>[] = [DISCOVER_SAVED_FEED, TIMELINE_SAVED_FEED] >[] = [DISCOVER_SAVED_FEED, TIMELINE_SAVED_FEED]
export const KNOWN_SHUTDOWN_FEEDS = [
'at://did:plc:wqowuobffl66jv3kpsvo7ak4/app.bsky.feed.generator/the-algorithm', // for you by skygaze
]
export const GIF_SERVICE = 'https://gifs.bsky.app' export const GIF_SERVICE = 'https://gifs.bsky.app'
export const GIF_SEARCH = (params: string) => export const GIF_SEARCH = (params: string) =>

View File

@ -14,6 +14,7 @@ import {useLingui} from '@lingui/react'
import {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
import {FALLBACK_MARKER_POST} from '#/lib/api/feed/home' import {FALLBACK_MARKER_POST} from '#/lib/api/feed/home'
import {KNOWN_SHUTDOWN_FEEDS} from '#/lib/constants'
import {logEvent} from '#/lib/statsig/statsig' import {logEvent} from '#/lib/statsig/statsig'
import {logger} from '#/logger' import {logger} from '#/logger'
import {isWeb} from '#/platform/detection' import {isWeb} from '#/platform/detection'
@ -36,12 +37,14 @@ import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn' import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
import {DiscoverFallbackHeader} from './DiscoverFallbackHeader' import {DiscoverFallbackHeader} from './DiscoverFallbackHeader'
import {FeedErrorMessage} from './FeedErrorMessage' import {FeedErrorMessage} from './FeedErrorMessage'
import {FeedShutdownMsg} from './FeedShutdownMsg'
import {FeedSlice} from './FeedSlice' import {FeedSlice} from './FeedSlice'
const LOADING_ITEM = {_reactKey: '__loading__'} const LOADING_ITEM = {_reactKey: '__loading__'}
const EMPTY_FEED_ITEM = {_reactKey: '__empty__'} const EMPTY_FEED_ITEM = {_reactKey: '__empty__'}
const ERROR_ITEM = {_reactKey: '__error__'} const ERROR_ITEM = {_reactKey: '__error__'}
const LOAD_MORE_ERROR_ITEM = {_reactKey: '__load_more_error__'} const LOAD_MORE_ERROR_ITEM = {_reactKey: '__load_more_error__'}
const FEED_SHUTDOWN_MSG_ITEM = {_reactKey: '__feed_shutdown_msg_item__'}
// DISABLED need to check if this is causing random feed refreshes -prf // DISABLED need to check if this is causing random feed refreshes -prf
// const REFRESH_AFTER = STALE.HOURS.ONE // const REFRESH_AFTER = STALE.HOURS.ONE
@ -96,7 +99,7 @@ let Feed = ({
const [isPTRing, setIsPTRing] = React.useState(false) const [isPTRing, setIsPTRing] = React.useState(false)
const checkForNewRef = React.useRef<(() => void) | null>(null) const checkForNewRef = React.useRef<(() => void) | null>(null)
const lastFetchRef = React.useRef<number>(Date.now()) const lastFetchRef = React.useRef<number>(Date.now())
const feedType = feed.split('|')[0] const [feedType, feedUri] = feed.split('|')
const opts = React.useMemo( const opts = React.useMemo(
() => ({enabled, ignoreFilterFor}), () => ({enabled, ignoreFilterFor}),
@ -196,6 +199,9 @@ let Feed = ({
const feedItems = React.useMemo(() => { const feedItems = React.useMemo(() => {
let arr: any[] = [] let arr: any[] = []
if (KNOWN_SHUTDOWN_FEEDS.includes(feedUri)) {
arr = arr.concat([FEED_SHUTDOWN_MSG_ITEM])
}
if (isFetched) { if (isFetched) {
if (isError && isEmpty) { if (isError && isEmpty) {
arr = arr.concat([ERROR_ITEM]) arr = arr.concat([ERROR_ITEM])
@ -213,7 +219,7 @@ let Feed = ({
arr.push(LOADING_ITEM) arr.push(LOADING_ITEM)
} }
return arr return arr
}, [isFetched, isError, isEmpty, data]) }, [isFetched, isError, isEmpty, data, feedUri])
// events // events
// = // =
@ -296,6 +302,8 @@ let Feed = ({
) )
} else if (item === LOADING_ITEM) { } else if (item === LOADING_ITEM) {
return <PostFeedLoadingPlaceholder /> return <PostFeedLoadingPlaceholder />
} else if (item === FEED_SHUTDOWN_MSG_ITEM) {
return <FeedShutdownMsg feedUri={feedUri} />
} else if (item.rootUri === FALLBACK_MARKER_POST.post.uri) { } else if (item.rootUri === FALLBACK_MARKER_POST.post.uri) {
// HACK // HACK
// tell the user we fell back to discover // tell the user we fell back to discover
@ -307,6 +315,7 @@ let Feed = ({
}, },
[ [
feed, feed,
feedUri,
error, error,
onPressTryAgain, onPressTryAgain,
onPressRetryLoadMore, onPressRetryLoadMore,

View File

@ -0,0 +1,159 @@
import React from 'react'
import {View} from 'react-native'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {PROD_DEFAULT_FEED} from '#/lib/constants'
import {logger} from '#/logger'
import {
useAddSavedFeedsMutation,
usePreferencesQuery,
useRemoveFeedMutation,
useUpdateSavedFeedsMutation,
} from '#/state/queries/preferences'
import {useSetSelectedFeed} from '#/state/shell/selected-feed'
import * as Toast from '#/view/com/util/Toast'
import {atoms as a, useTheme} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import {InlineLinkText} from '#/components/Link'
import {Loader} from '#/components/Loader'
import {Text} from '#/components/Typography'
export function FeedShutdownMsg({feedUri}: {feedUri: string}) {
const t = useTheme()
const {_} = useLingui()
const setSelectedFeed = useSetSelectedFeed()
const {data: preferences} = usePreferencesQuery()
const {mutateAsync: addSavedFeeds, isPending: isAddSavedFeedPending} =
useAddSavedFeedsMutation()
const {mutateAsync: removeFeed, isPending: isRemovePending} =
useRemoveFeedMutation()
const {mutateAsync: updateSavedFeeds, isPending: isUpdateFeedPending} =
useUpdateSavedFeedsMutation()
const feedConfig = preferences?.savedFeeds?.find(
f => f.value === feedUri && f.pinned,
)
const discoverFeedConfig = preferences?.savedFeeds?.find(
f => f.value === PROD_DEFAULT_FEED('whats-hot'),
)
const hasFeedPinned = Boolean(feedConfig)
const hasDiscoverPinned = Boolean(discoverFeedConfig?.pinned)
const onRemoveFeed = React.useCallback(async () => {
try {
if (feedConfig) {
await removeFeed(feedConfig)
Toast.show(_(msg`Removed from your feeds`))
}
} catch (err: any) {
Toast.show(
_(
msg`There was an an issue updating your feeds, please check your internet connection and try again.`,
),
)
logger.error('Failed up update feeds', {message: err})
}
}, [removeFeed, feedConfig, _])
const onReplaceFeed = React.useCallback(async () => {
try {
if (!discoverFeedConfig) {
await addSavedFeeds([
{
type: 'feed',
value: PROD_DEFAULT_FEED('whats-hot'),
pinned: true,
},
])
} else {
await updateSavedFeeds([
{
...discoverFeedConfig,
pinned: true,
},
])
}
setSelectedFeed(`feedgen|${PROD_DEFAULT_FEED('whats-hot')}`)
if (feedConfig) {
await removeFeed(feedConfig)
}
Toast.show(_(msg`The feed has been replaced with Discover.`))
} catch (err: any) {
Toast.show(
_(
msg`There was an an issue updating your feeds, please check your internet connection and try again.`,
),
)
logger.error('Failed up update feeds', {message: err})
}
}, [
addSavedFeeds,
updateSavedFeeds,
removeFeed,
discoverFeedConfig,
feedConfig,
setSelectedFeed,
_,
])
const isProcessing =
isAddSavedFeedPending || isUpdateFeedPending || isRemovePending
return (
<View
style={[
a.py_3xl,
a.px_2xl,
a.gap_xl,
t.atoms.border_contrast_low,
a.border_t,
]}>
<Text style={[a.text_5xl, a.font_bold, t.atoms.text, a.text_center]}>
:(
</Text>
<Text style={[a.text_md, a.leading_snug, t.atoms.text, a.text_center]}>
<Trans>
This feed is no longer online. We are showing{' '}
<InlineLinkText
to="/profile/bsky.app/feed/whats-hot"
style={[a.text_md]}>
Discover
</InlineLinkText>{' '}
instead.
</Trans>
</Text>
{hasFeedPinned ? (
<View style={[a.flex_row, a.justify_center, a.gap_sm]}>
<Button
variant="outline"
color="primary"
size="small"
label={_(msg`Remove feed`)}
disabled={isProcessing}
onPress={onRemoveFeed}>
<ButtonText>
<Trans>Remove feed</Trans>
</ButtonText>
{isRemovePending && <ButtonIcon icon={Loader} />}
</Button>
{!hasDiscoverPinned && (
<Button
variant="solid"
color="primary"
size="small"
label={_(msg`Replace with Discover`)}
disabled={isProcessing}
onPress={onReplaceFeed}>
<ButtonText>
<Trans>Replace with Discover</Trans>
</ButtonText>
{(isAddSavedFeedPending || isUpdateFeedPending) && (
<ButtonIcon icon={Loader} />
)}
</Button>
)}
</View>
) : undefined}
</View>
)
}