This commit is contained in:
Eric Bailey
2024-07-03 14:02:28 -05:00
parent db5cf919dc
commit dc21472525
4 changed files with 218 additions and 0 deletions
@@ -0,0 +1,88 @@
import React from 'react'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {
ProgressGuideToast,
ProgressGuideToastRef,
} from '#/components/ProgressGuide/Toast'
import {useNudges, NudgeType} from '#/components/nudges'
export type Action = {
type: 'activate'
} | {
type: 'like'
}
export function useProgressGuide() {
const {nudges, activateNudges, updateNudges, dismissNudges} = useNudges()
const firstLikeToastRef = React.useRef<ProgressGuideToastRef | null>(null)
const fifthLikeToastRef = React.useRef<ProgressGuideToastRef | null>(null)
const tenthLikeToastRef = React.useRef<ProgressGuideToastRef | null>(null)
const isActive = Boolean(nudges.find(n => n.type === NudgeType.progressGuide_like10Follow7))
const dispatch = (action: Action) => {
const prevState = nudges.find(n => n.type === NudgeType.progressGuide_like10Follow7)
if (!prevState || prevState.type !== NudgeType.progressGuide_like10Follow7) return
let next = prevState
switch (action.type) {
case 'activate': {
activateNudges([
{
type: NudgeType.progressGuide_like10Follow7,
numLikes: 0,
numFollows: 0,
complete: false,
},
])
break;
}
case 'like': {
next = {
...next,
numLikes: prevState.numLikes + 1,
}
break;
}
default:
}
}
return {
isActive,
dispatch,
refs: {
firstLikeToastRef,
fifthLikeToastRef,
tenthLikeToastRef,
},
}
}
export function Toasts() {
const {_} = useLingui()
const {isActive, refs} = useProgressGuide()
return isActive ? (
<>
<ProgressGuideToast
ref={refs.firstLikeToastRef}
title={_(msg`Your first like!`)}
subtitle={_(msg`Like 10 posts to train the Discover feed`)}
/>
<ProgressGuideToast
ref={refs.fifthLikeToastRef}
title={_(msg`Half way there!`)}
subtitle={_(msg`Like 10 posts to train the Discover feed`)}
/>
<ProgressGuideToast
ref={refs.tenthLikeToastRef}
title={_(msg`Task complete - 10 likes!`)}
subtitle={_(msg`The Discover feed now knows what you like`)}
/>
</>
) : null
}
+53
View File
@@ -0,0 +1,53 @@
import React from 'react'
import {Nudge} from '#/components/nudges/types'
export * from '#/components/nudges/types'
export type Context = {
nudges: Nudge[]
activateNudges: (nudges: Nudge[]) => Promise<void>
updateNudges: (nudges: Nudge[]) => Promise<void>
dismissNudges: (nudges: Nudge[]) => Promise<void>
}
const Context = React.createContext<Context>({
nudges: [],
activateNudges: async () => {},
updateNudges: async () => {},
dismissNudges: async () => {},
})
export function useNudges() {
return React.useContext(Context)
}
export function NudgeProvider({children}: {children: React.ReactNode}) {
// TODO hydrate from remote storage
const [nudges, setNudges] = React.useState<Nudge[]>([])
const activateNudges = async (nudges: Nudge[]) => {
setNudges(s => Array.from(new Set([...s, ...nudges])))
// TODO write to remote storage
}
const updateNudges = async (nudges: Nudge[]) => {
setNudges(s => [
...s.filter(n => !nudges.some(nudge => nudge.type === n.type)),
...nudges,
])
// TODO write to remote storage
}
const dismissNudges = async (nudges: Nudge[]) => {
setNudges(s => s.filter(n => !nudges.some(nudge => nudge.type === n.type)))
// TODO write to remote storage
}
const ctx = React.useMemo<Context>(
() => ({nudges, activateNudges, updateNudges, dismissNudges}),
[nudges],
)
return <Context.Provider value={ctx}>{children}</Context.Provider>
}
+29
View File
@@ -0,0 +1,29 @@
export enum NudgeType {
/*
* Feed interstitials
*/
interstitialPopularFeeds = 'interstitialPopularFeeds',
interstitialSuggestedFollows = 'interstitialSuggestedFollows',
/*
* Progress guides
*/
progressGuide_like10Follow7 = 'progressGuide_like10Follow7',
}
export type Interstitials = {
type: NudgeType.interstitialPopularFeeds
hidden: boolean
} | {
type: NudgeType.interstitialSuggestedFollows
hidden: boolean
}
export type ProgressGuides = {
type: NudgeType.progressGuide_like10Follow7
numLikes: number
numFollows: number
complete: boolean
}
export type Nudge = Interstitials | ProgressGuides
+48
View File
@@ -0,0 +1,48 @@
// import {useQueueNudgesMutation, useDismissNudgesMutation} from '#/state/queries/preferences'
export enum NudgeType {
/*
* Feed interstitials
*/
interstitialPopularFeeds = 'interstitialPopularFeeds',
interstitialSuggestedFollows = 'interstitialSuggestedFollows',
/*
* Progress guides
*/
progressGuide_like10Follow7 = 'progressGuide_like10Follow7',
}
export type Interstitials = {
type: NudgeType.interstitialPopularFeeds
} | {
type: NudgeType.interstitialSuggestedFollows
}
export type ProgressGuides = {
type: NudgeType.progressGuide_like10Follow7
numLikes: number
numFollows: number
}
export type Nudge = Interstitials | ProgressGuides
let __temp_storage: Nudge[] = []
export function useQueueNudges() {
const queueNudges = async (nudges: Nudge[]) => {
__temp_storage.push(...nudges)
}
return { queueNudges }
}
export function useDismissNudges() {
const dismissNudges = async (nudges: Nudge[]) => {
__temp_storage = __temp_storage.filter(n => {
return !nudges.some(nudge => nudge.type === n.type)
})
}
return { dismissNudges }
}