This commit is contained in:
Eric Bailey
2024-04-17 20:27:49 -05:00
parent 38ce57acf1
commit 6f35e50dbf
10 changed files with 91 additions and 80 deletions
@@ -5,7 +5,7 @@ import {useLingui} from '@lingui/react'
import {DialogOuterProps} from '#/components/Dialog'
import * as Prompt from '#/components/Prompt'
export function HomeAlgoNoticeDialog({
export function PrimaryAlgoNoticeDialog({
control,
}: {
control: DialogOuterProps['control']
@@ -13,9 +13,9 @@ export function HomeAlgoNoticeDialog({
const {_} = useLingui()
return (
<Prompt.Outer control={control}>
<Prompt.TitleText>Your home algorithm</Prompt.TitleText>
<Prompt.TitleText>Your primary algorithm</Prompt.TitleText>
<Prompt.DescriptionText>
This feed is set as your home algorithm, which is used as your home
This feed is set as your primary algorithm, which is used as your home
screen when you open the app.
</Prompt.DescriptionText>
<Prompt.Actions>
+17 -13
View File
@@ -238,13 +238,13 @@ const DISCOVER_FEED_STUB: FeedSourceInfo = {
likeCount: 0,
likeUri: '',
}
const HOME_ALGO_FEED_STUB: FeedSourceInfo = {
const PRIMARY_ALGO_STUB: FeedSourceInfo = {
type: 'feed',
displayName: 'Home',
uri: 'home-algo',
displayName: 'For You',
uri: 'primary-algo',
route: {
href: '/',
name: 'Home',
name: 'For You',
params: {},
},
cid: '',
@@ -261,18 +261,18 @@ const pinnedFeedInfosQueryKeyRoot = 'pinnedFeedsInfos'
export function usePinnedFeedsInfos() {
const {hasSession} = useSession()
const {data: preferences, isLoading: isLoadingPrefs} = usePreferencesQuery()
const isHomeAlgoExperimentEnabled = useGate(
const isPrimaryAlgoExperimentEnabled = useGate(
'reduced_onboarding_and_home_algo',
)
const pinnedUris = (preferences?.feeds?.pinned ?? []).filter(f => {
if (
isHomeAlgoExperimentEnabled &&
isPrimaryAlgoExperimentEnabled &&
hasSession &&
preferences?.homeAlgo &&
preferences?.homeAlgo?.enabled
preferences?.primaryAlgorithm &&
preferences?.primaryAlgorithm?.enabled
) {
// remove duplicate feed
return f !== preferences?.homeAlgo.uri
return f !== preferences?.primaryAlgorithm.uri
}
return true
})
@@ -323,11 +323,15 @@ export function usePinnedFeedsInfos() {
// The returned result will have the original order.
let result = [hasSession ? HOME_FEED_STUB : DISCOVER_FEED_STUB]
if (isHomeAlgoExperimentEnabled && hasSession && preferences?.homeAlgo) {
const {enabled, uri} = preferences.homeAlgo
// ONLY add the home algo if we have a URI set
if (
isPrimaryAlgoExperimentEnabled &&
hasSession &&
preferences?.primaryAlgorithm
) {
const {enabled, uri} = preferences.primaryAlgorithm
// ONLY add the primary algo if we have a URI set
if (enabled && uri) {
result = [HOME_ALGO_FEED_STUB, HOME_FEED_STUB]
result = [PRIMARY_ALGO_STUB, HOME_FEED_STUB]
}
}
+1 -1
View File
@@ -44,7 +44,7 @@ type AuthorFilter =
type FeedUri = string
type ListUri = string
export type FeedDescriptor =
| 'home-algo'
| 'primary-algo'
| 'home'
| 'following'
| `author|${ActorDid}|${AuthorFilter}`
+1 -1
View File
@@ -45,5 +45,5 @@ export const DEFAULT_LOGGED_OUT_PREFERENCES: UsePreferencesQueryResponse = {
threadViewPrefs: DEFAULT_THREAD_VIEW_PREFS,
userAge: 13, // TODO(pwi)
interests: {tags: []},
homeAlgo: {enabled: undefined},
primaryAlgorithm: {enabled: undefined},
}
+3 -4
View File
@@ -3,7 +3,6 @@ import {
AppBskyActorDefs,
BSKY_LABELER_DID,
BskyFeedViewPreference,
BskyHomeAlgoPreference,
LabelPreference,
ModerationOpts,
} from '@atproto/api'
@@ -347,12 +346,12 @@ export function useRemoveMutedWordMutation() {
})
}
export function useSetHomeAlgoMutation() {
export function useSetPrimaryAlgorithmMutation() {
const queryClient = useQueryClient()
return useMutation({
mutationFn: async (pref: BskyHomeAlgoPreference) => {
await getAgent().setHomeAlgoPref(pref)
mutationFn: async (pref: AppBskyActorDefs.PrimaryAlgoPref) => {
await getAgent().setPrimaryAlgorithm(pref)
// triggers a refetch
await queryClient.invalidateQueries({
queryKey: preferencesQueryKey,
+14 -12
View File
@@ -25,8 +25,8 @@ import * as Toast from 'view/com/util/Toast'
import {useTheme} from '#/alf'
import {atoms as a} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import {HomeAlgoNoticeDialog} from '#/components/HomeAlgoNoticeDialog'
import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
import {PrimaryAlgoNoticeDialog} from '#/components/PrimaryAlgoNoticeDialog'
import * as Prompt from '#/components/Prompt'
import {RichText} from '#/components/RichText'
import {Text} from '../util/text/Text'
@@ -93,10 +93,10 @@ export function FeedSourceCardLoaded({
const {_} = useLingui()
const removePromptControl = Prompt.usePromptControl()
const navigation = useNavigationDeduped()
const isHomeAlgoExperimentEnabled = useGate(
const isPrimaryAlgoExperimentEnabled = useGate(
'reduced_onboarding_and_home_algo',
)
const homeAlgoDialogControl = Prompt.usePromptControl()
const primaryAlgoDialogControl = Prompt.usePromptControl()
const {isPending: isSavePending, mutateAsync: saveFeed} =
useSaveFeedMutation()
@@ -196,10 +196,10 @@ export function FeedSourceCardLoaded({
)
const showFeedSaveButton = showSaveBtn && feed.type === 'feed'
const isHomeAlgo =
preferences.homeAlgo?.enabled &&
preferences.homeAlgo?.uri &&
preferences.homeAlgo.uri === feed.uri
const isPrimaryAlgo =
preferences.primaryAlgorithm?.enabled &&
preferences.primaryAlgorithm?.uri &&
preferences.primaryAlgorithm.uri === feed.uri
return (
<>
@@ -239,17 +239,19 @@ export function FeedSourceCardLoaded({
</View>
{showFeedSaveButton &&
(isHomeAlgoExperimentEnabled && isHomeAlgo ? (
(isPrimaryAlgoExperimentEnabled && isPrimaryAlgo ? (
<Button
variant="solid"
color="secondary"
size="small"
label={_(msg`This feed is already set as your home algorithm.`)}
label={_(
msg`This feed is already set as your primary algorithm.`,
)}
onPress={() => {
homeAlgoDialogControl.open()
primaryAlgoDialogControl.open()
}}>
<ButtonIcon icon={Check} position="left" />
<ButtonText>Home Algo</ButtonText>
<ButtonText>Primary Algorithm</ButtonText>
</Button>
) : (
<View style={[s.justifyCenter]}>
@@ -313,7 +315,7 @@ export function FeedSourceCardLoaded({
confirmButtonColor="negative"
/>
<HomeAlgoNoticeDialog control={homeAlgoDialogControl} />
<PrimaryAlgoNoticeDialog control={primaryAlgoDialogControl} />
</>
)
}
+1 -1
View File
@@ -25,7 +25,7 @@ export function HomeHeader(
const hasPinnedCustom = React.useMemo<boolean>(() => {
if (!hasSession) return false
return feeds.some(
tab => !['home', 'home-algo', 'following'].includes(tab.uri),
tab => !['home', 'primary-algo', 'following'].includes(tab.uri),
)
}, [feeds, hasSession])
+14 -10
View File
@@ -54,7 +54,7 @@ function HomeScreenReady({
pinnedFeedInfos: FeedSourceInfo[]
}) {
useOTAUpdates()
const isHomeAlgoExperimentEnabled = useGate(
const isPrimaryAlgoExperimentEnabled = useGate(
'reduced_onboarding_and_home_algo',
)
@@ -65,18 +65,18 @@ function HomeScreenReady({
feeds.push(`feedgen|${uri}`)
} else if (uri.includes('app.bsky.graph.list')) {
feeds.push(`list|${uri}`)
} else if (uri === 'home-algo') {
} else if (uri === 'primary-algo') {
if (
isHomeAlgoExperimentEnabled &&
preferences.homeAlgo.enabled &&
preferences.homeAlgo.uri
isPrimaryAlgoExperimentEnabled &&
preferences.primaryAlgorithm.enabled &&
preferences.primaryAlgorithm.uri
) {
feeds.push(`feedgen|${preferences.homeAlgo.uri}`)
feeds.push(`feedgen|${preferences.primaryAlgorithm.uri}`)
} else {
// should never happen - esb
logger.error(`home-algo feed expected, but no URI found`, {
isHomeAlgoExperimentEnabled,
homeAlgo: preferences.homeAlgo,
logger.error(`primary-algo feed expected, but no URI found`, {
isPrimaryAlgoExperimentEnabled,
primaryAlgorithm: preferences.primaryAlgorithm,
})
feeds.push(`feedgen|${DISCOVER_FEED_URI}`)
}
@@ -87,7 +87,11 @@ function HomeScreenReady({
}
}
return feeds
}, [pinnedFeedInfos, isHomeAlgoExperimentEnabled, preferences.homeAlgo])
}, [
pinnedFeedInfos,
isPrimaryAlgoExperimentEnabled,
preferences.primaryAlgorithm,
])
const rawSelectedFeed = useSelectedFeed()
const setSelectedFeed = useSetSelectedFeed()
+35 -33
View File
@@ -21,7 +21,7 @@ import {
UsePreferencesQueryResponse,
useRemoveFeedMutation,
useSaveFeedMutation,
useSetHomeAlgoMutation,
useSetPrimaryAlgorithmMutation,
useUnpinFeedMutation,
} from '#/state/queries/preferences'
import {useResolveUriQuery} from '#/state/queries/resolve-uri'
@@ -56,7 +56,6 @@ import {CenteredView} from 'view/com/util/Views'
import {atoms as a, useTheme} from '#/alf'
import {Button as NewButton, ButtonIcon, ButtonText} from '#/components/Button'
import {useDialogControl} from '#/components/Dialog'
import {HomeAlgoNoticeDialog} from '#/components/HomeAlgoNoticeDialog'
import {ArrowOutOfBox_Stroke2_Corner0_Rounded as Share} from '#/components/icons/ArrowOutOfBox'
import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
@@ -70,6 +69,7 @@ import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus
import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash'
import {InlineLinkText} from '#/components/Link'
import * as Menu from '#/components/Menu'
import {PrimaryAlgoNoticeDialog} from '#/components/PrimaryAlgoNoticeDialog'
import {ReportDialog, useReportDialogControl} from '#/components/ReportDialog'
import {RichText} from '#/components/RichText'
@@ -168,10 +168,10 @@ export function ProfileFeedScreenInner({
const playHaptic = useHaptics()
const feedSectionRef = React.useRef<SectionRef>(null)
const isScreenFocused = useIsFocused()
const isHomeAlgoExperimentEnabled = useGate(
const isPrimaryAlgoExperimentEnabled = useGate(
'reduced_onboarding_and_home_algo',
)
const homeAlgoDialogControl = useDialogControl()
const primaryAlgoDialogControl = useDialogControl()
const {
mutateAsync: saveFeed,
@@ -198,10 +198,10 @@ export function ProfileFeedScreenInner({
isPending: isUnpinPending,
} = useUnpinFeedMutation()
const {
mutateAsync: setHomeAlgo,
variables: homeAlgoVariables,
isPending: isSetHomeAlgoPending,
} = useSetHomeAlgoMutation()
mutateAsync: setPrimaryAlgo,
variables: primaryAlgoVariables,
isPending: isSetPrimaryAlgoPending,
} = useSetPrimaryAlgorithmMutation()
const isSaved =
!removedFeed &&
@@ -209,11 +209,11 @@ export function ProfileFeedScreenInner({
const isPinned =
!unpinnedFeed &&
(!!pinnedFeed || preferences.feeds.pinned.includes(feedInfo.uri))
const isHomeAlgo =
(preferences.homeAlgo?.enabled &&
preferences.homeAlgo?.uri &&
preferences.homeAlgo.uri === feedInfo.uri) ||
(homeAlgoVariables?.enabled && homeAlgoVariables.uri === feedInfo.uri)
const isPrimaryAlgo =
(preferences.primaryAlgorithm?.enabled &&
preferences.primaryAlgorithm?.uri &&
preferences.primaryAlgorithm.uri === feedInfo.uri) ||
(primaryAlgoVariables?.enabled && primaryAlgoVariables.uri === feedInfo.uri)
useSetTitle(feedInfo?.displayName)
@@ -278,15 +278,17 @@ export function ProfileFeedScreenInner({
_,
])
const onSetHomeAlgo = React.useCallback(async () => {
const onSetPrimaryAlgo = React.useCallback(async () => {
try {
playHaptic()
await setHomeAlgo({enabled: true, uri: feedInfo.uri})
await setPrimaryAlgo({enabled: true, uri: feedInfo.uri})
} catch (e: any) {
Toast.show(_(msg`There was an issue contacting the server`))
logger.error('ProfileFeed: failed to set home algo', {message: e.message})
logger.error('ProfileFeed: failed to set primary algo', {
message: e.message,
})
}
}, [setHomeAlgo, feedInfo, _, playHaptic])
}, [setPrimaryAlgo, feedInfo, _, playHaptic])
const onPressShare = React.useCallback(() => {
const url = toShareUrl(feedInfo.route.href)
@@ -325,19 +327,19 @@ export function ProfileFeedScreenInner({
<View style={[a.flex_row, a.align_center, a.gap_sm]}>
{feedInfo &&
hasSession &&
(isHomeAlgoExperimentEnabled && isHomeAlgo ? (
(isPrimaryAlgoExperimentEnabled && isPrimaryAlgo ? (
<NewButton
variant="solid"
color="secondary"
size="small"
label={_(
msg`This feed is already set as your home algorithm.`,
msg`This feed is already set as your primary algorithm.`,
)}
onPress={() => {
homeAlgoDialogControl.open()
primaryAlgoDialogControl.open()
}}>
<ButtonIcon icon={Check} position="left" />
<ButtonText>Home Algo</ButtonText>
<ButtonText>Primary Algorithm</ButtonText>
</NewButton>
) : (
<NewButton
@@ -386,7 +388,7 @@ export function ProfileFeedScreenInner({
<Menu.Group>
{hasSession && (
<>
{!isHomeAlgo && (
{!isPrimaryAlgo && (
<>
<Menu.Item
disabled={isSavePending || isRemovePending}
@@ -409,12 +411,12 @@ export function ProfileFeedScreenInner({
</Menu.Item>
<Menu.Item
disabled={isSetHomeAlgoPending}
testID="feedHeaderDropdownSetHomeAlgoBtn"
label={_(msg`Set as home algorithm`)}
onPress={onSetHomeAlgo}>
disabled={isSetPrimaryAlgoPending}
testID="feedHeaderDropdownSetPrimaryAlgoBtn"
label={_(msg`Set as primary algorithm`)}
onPress={onSetPrimaryAlgo}>
<Menu.ItemText>
{_(msg`Set as home algorithm`)}
{_(msg`Set as primary algorithm`)}
</Menu.ItemText>
<Menu.ItemIcon icon={Home} position="right" />
</Menu.Item>
@@ -449,7 +451,7 @@ export function ProfileFeedScreenInner({
feedInfo={feedInfo}
/>
<HomeAlgoNoticeDialog control={homeAlgoDialogControl} />
<PrimaryAlgoNoticeDialog control={primaryAlgoDialogControl} />
</>
)
}, [
@@ -468,11 +470,11 @@ export function ProfileFeedScreenInner({
onPressReport,
onPressShare,
t,
isHomeAlgoExperimentEnabled,
isHomeAlgo,
homeAlgoDialogControl,
onSetHomeAlgo,
isSetHomeAlgoPending,
isPrimaryAlgoExperimentEnabled,
isPrimaryAlgo,
primaryAlgoDialogControl,
onSetPrimaryAlgo,
isSetPrimaryAlgoPending,
])
return (
+2 -2
View File
@@ -36,8 +36,8 @@ export function DesktopFeeds() {
let feed: FeedDescriptor
if (uri === 'home') {
feed = 'home'
} else if (uri === 'home-algo') {
feed = 'home-algo'
} else if (uri === 'primary-algo') {
feed = 'primary-algo'
} else if (uri.includes('app.bsky.feed.generator')) {
feed = `feedgen|${uri}`
} else if (uri.includes('app.bsky.graph.list')) {