WIP
This commit is contained in:
@@ -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
|
||||
}
|
||||
@@ -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>
|
||||
}
|
||||
@@ -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
|
||||
@@ -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 }
|
||||
}
|
||||
Reference in New Issue
Block a user