diff options
author | Paul Frazee <pfrazee@gmail.com> | 2024-05-10 21:57:21 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-11 05:57:21 +0100 |
commit | 6f5b551bdaa133ec6fa0f91f3f9621542b4217a8 (patch) | |
tree | 2b48ece53700b373d03707acef1fc3d96b817eff | |
parent | d0440d087eb219639c3deb782e378eb2f1f97058 (diff) | |
download | voidsky-6f5b551bdaa133ec6fa0f91f3f9621542b4217a8.tar.zst |
Add shutdown message to for you feed (#3776)
-rw-r--r-- | src/lib/constants.ts | 4 | ||||
-rw-r--r-- | src/view/com/posts/Feed.tsx | 13 | ||||
-rw-r--r-- | src/view/com/posts/FeedShutdownMsg.tsx | 159 |
3 files changed, 174 insertions, 2 deletions
diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 83f513911..051ed4d59 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -111,6 +111,10 @@ export const RECOMMENDED_SAVED_FEEDS: Pick< 'type' | 'value' | 'pinned' >[] = [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_SEARCH = (params: string) => diff --git a/src/view/com/posts/Feed.tsx b/src/view/com/posts/Feed.tsx index c51733d1b..e45abfedc 100644 --- a/src/view/com/posts/Feed.tsx +++ b/src/view/com/posts/Feed.tsx @@ -14,6 +14,7 @@ import {useLingui} from '@lingui/react' import {useQueryClient} from '@tanstack/react-query' import {FALLBACK_MARKER_POST} from '#/lib/api/feed/home' +import {KNOWN_SHUTDOWN_FEEDS} from '#/lib/constants' import {logEvent} from '#/lib/statsig/statsig' import {logger} from '#/logger' import {isWeb} from '#/platform/detection' @@ -36,12 +37,14 @@ import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder' import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn' import {DiscoverFallbackHeader} from './DiscoverFallbackHeader' import {FeedErrorMessage} from './FeedErrorMessage' +import {FeedShutdownMsg} from './FeedShutdownMsg' import {FeedSlice} from './FeedSlice' const LOADING_ITEM = {_reactKey: '__loading__'} const EMPTY_FEED_ITEM = {_reactKey: '__empty__'} const ERROR_ITEM = {_reactKey: '__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 // const REFRESH_AFTER = STALE.HOURS.ONE @@ -96,7 +99,7 @@ let Feed = ({ const [isPTRing, setIsPTRing] = React.useState(false) const checkForNewRef = React.useRef<(() => void) | null>(null) const lastFetchRef = React.useRef<number>(Date.now()) - const feedType = feed.split('|')[0] + const [feedType, feedUri] = feed.split('|') const opts = React.useMemo( () => ({enabled, ignoreFilterFor}), @@ -196,6 +199,9 @@ let Feed = ({ const feedItems = React.useMemo(() => { let arr: any[] = [] + if (KNOWN_SHUTDOWN_FEEDS.includes(feedUri)) { + arr = arr.concat([FEED_SHUTDOWN_MSG_ITEM]) + } if (isFetched) { if (isError && isEmpty) { arr = arr.concat([ERROR_ITEM]) @@ -213,7 +219,7 @@ let Feed = ({ arr.push(LOADING_ITEM) } return arr - }, [isFetched, isError, isEmpty, data]) + }, [isFetched, isError, isEmpty, data, feedUri]) // events // = @@ -296,6 +302,8 @@ let Feed = ({ ) } else if (item === LOADING_ITEM) { return <PostFeedLoadingPlaceholder /> + } else if (item === FEED_SHUTDOWN_MSG_ITEM) { + return <FeedShutdownMsg feedUri={feedUri} /> } else if (item.rootUri === FALLBACK_MARKER_POST.post.uri) { // HACK // tell the user we fell back to discover @@ -307,6 +315,7 @@ let Feed = ({ }, [ feed, + feedUri, error, onPressTryAgain, onPressRetryLoadMore, diff --git a/src/view/com/posts/FeedShutdownMsg.tsx b/src/view/com/posts/FeedShutdownMsg.tsx new file mode 100644 index 000000000..bc047e831 --- /dev/null +++ b/src/view/com/posts/FeedShutdownMsg.tsx @@ -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> + ) +} |