Merge branch 'ansh/app-812-add-custom-feed-discovery-to-onboarding' into main
This commit is contained in:
commit
f9cab178b9
29 changed files with 1033 additions and 217 deletions
94
src/state/models/discovery/onboarding.ts
Normal file
94
src/state/models/discovery/onboarding.ts
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
import {makeAutoObservable} from 'mobx'
|
||||
import {RootStoreModel} from '../root-store'
|
||||
import {hasProp} from 'lib/type-guards'
|
||||
import {track} from 'lib/analytics/analytics'
|
||||
|
||||
export const OnboardingScreenSteps = {
|
||||
Welcome: 'Welcome',
|
||||
RecommendedFeeds: 'RecommendedFeeds',
|
||||
Home: 'Home',
|
||||
} as const
|
||||
|
||||
type OnboardingStep =
|
||||
(typeof OnboardingScreenSteps)[keyof typeof OnboardingScreenSteps]
|
||||
const OnboardingStepsArray = Object.values(OnboardingScreenSteps)
|
||||
export class OnboardingModel {
|
||||
// state
|
||||
step: OnboardingStep = 'Home' // default state to skip onboarding, only enabled for new users by calling start()
|
||||
|
||||
constructor(public rootStore: RootStoreModel) {
|
||||
makeAutoObservable(this, {
|
||||
rootStore: false,
|
||||
hydrate: false,
|
||||
serialize: false,
|
||||
})
|
||||
}
|
||||
|
||||
serialize(): unknown {
|
||||
return {
|
||||
step: this.step,
|
||||
}
|
||||
}
|
||||
|
||||
hydrate(v: unknown) {
|
||||
if (typeof v === 'object' && v !== null) {
|
||||
if (
|
||||
hasProp(v, 'step') &&
|
||||
typeof v.step === 'string' &&
|
||||
OnboardingStepsArray.includes(v.step as OnboardingStep)
|
||||
) {
|
||||
this.step = v.step as OnboardingStep
|
||||
}
|
||||
} else {
|
||||
// if there is no valid state, we'll just reset
|
||||
this.reset()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the next screen in the onboarding process based on the current step or screen name provided.
|
||||
* @param {OnboardingStep} [currentScreenName]
|
||||
* @returns name of next screen in the onboarding process
|
||||
*/
|
||||
next(currentScreenName?: OnboardingStep) {
|
||||
currentScreenName = currentScreenName || this.step
|
||||
if (currentScreenName === 'Welcome') {
|
||||
this.step = 'RecommendedFeeds'
|
||||
return this.step
|
||||
} else if (this.step === 'RecommendedFeeds') {
|
||||
this.finish()
|
||||
return this.step
|
||||
} else {
|
||||
// if we get here, we're in an invalid state, let's just go Home
|
||||
return 'Home'
|
||||
}
|
||||
}
|
||||
|
||||
start() {
|
||||
this.step = 'Welcome'
|
||||
track('Onboarding:Begin')
|
||||
}
|
||||
|
||||
finish() {
|
||||
this.step = 'Home'
|
||||
track('Onboarding:Complete')
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.step = 'Welcome'
|
||||
track('Onboarding:Reset')
|
||||
}
|
||||
|
||||
skip() {
|
||||
this.step = 'Home'
|
||||
track('Onboarding:Skipped')
|
||||
}
|
||||
|
||||
get isComplete() {
|
||||
return this.step === 'Home'
|
||||
}
|
||||
|
||||
get isActive() {
|
||||
return !this.isComplete
|
||||
}
|
||||
}
|
||||
|
|
@ -67,6 +67,19 @@ export class CustomFeedModel {
|
|||
}
|
||||
}
|
||||
|
||||
async pin() {
|
||||
try {
|
||||
await this.rootStore.preferences.addPinnedFeed(this.uri)
|
||||
} catch (error) {
|
||||
this.rootStore.log.error('Failed to pin feed', error)
|
||||
} finally {
|
||||
track('CustomFeed:Pin', {
|
||||
name: this.data.displayName,
|
||||
uri: this.uri,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async unsave() {
|
||||
try {
|
||||
await this.rootStore.preferences.removeSavedFeed(this.uri)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import {reset as resetNavigation} from '../../Navigation'
|
|||
// remove after backend testing finishes
|
||||
// -prf
|
||||
import {applyDebugHeader} from 'lib/api/debug-appview-proxy-header'
|
||||
import {OnboardingModel} from './discovery/onboarding'
|
||||
|
||||
export const appInfo = z.object({
|
||||
build: z.string(),
|
||||
|
|
@ -44,6 +45,7 @@ export class RootStoreModel {
|
|||
shell = new ShellUiModel(this)
|
||||
preferences = new PreferencesModel(this)
|
||||
me = new MeModel(this)
|
||||
onboarding = new OnboardingModel(this)
|
||||
invitedUsers = new InvitedUsers(this)
|
||||
handleResolutions = new HandleResolutionsCache()
|
||||
profiles = new ProfilesCache(this)
|
||||
|
|
@ -70,6 +72,7 @@ export class RootStoreModel {
|
|||
appInfo: this.appInfo,
|
||||
session: this.session.serialize(),
|
||||
me: this.me.serialize(),
|
||||
onboarding: this.onboarding.serialize(),
|
||||
shell: this.shell.serialize(),
|
||||
preferences: this.preferences.serialize(),
|
||||
invitedUsers: this.invitedUsers.serialize(),
|
||||
|
|
@ -88,6 +91,9 @@ export class RootStoreModel {
|
|||
if (hasProp(v, 'me')) {
|
||||
this.me.hydrate(v.me)
|
||||
}
|
||||
if (hasProp(v, 'onboarding')) {
|
||||
this.onboarding.hydrate(v.onboarding)
|
||||
}
|
||||
if (hasProp(v, 'session')) {
|
||||
this.session.hydrate(v.session)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,10 +109,10 @@ export class CreateAccountModel {
|
|||
this.setError('')
|
||||
this.setIsProcessing(true)
|
||||
|
||||
// open the onboarding modal after the session is created
|
||||
// open the onboarding screens after the session is created
|
||||
const sessionReadySub = this.rootStore.onSessionReady(() => {
|
||||
sessionReadySub.remove()
|
||||
this.rootStore.shell.openModal({name: 'onboarding'})
|
||||
this.rootStore.onboarding.start()
|
||||
})
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -136,10 +136,6 @@ export interface PostLanguagesSettingsModal {
|
|||
name: 'post-languages-settings'
|
||||
}
|
||||
|
||||
export interface OnboardingModal {
|
||||
name: 'onboarding'
|
||||
}
|
||||
|
||||
export type Modal =
|
||||
// Account
|
||||
| AddAppPasswordModal
|
||||
|
|
@ -171,9 +167,6 @@ export type Modal =
|
|||
| WaitlistModal
|
||||
| InviteCodesModal
|
||||
|
||||
// Onboarding
|
||||
| OnboardingModal
|
||||
|
||||
// Generic
|
||||
| ConfirmModal
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue