Move reminders to new persisted state layer (#1834)
parent
96d8faf4b0
commit
2acc88e78d
|
@ -20,7 +20,6 @@ import {PreferencesModel} from './ui/preferences'
|
||||||
import {resetToTab} from '../../Navigation'
|
import {resetToTab} from '../../Navigation'
|
||||||
import {ImageSizesCache} from './cache/image-sizes'
|
import {ImageSizesCache} from './cache/image-sizes'
|
||||||
import {MutedThreads} from './muted-threads'
|
import {MutedThreads} from './muted-threads'
|
||||||
import {Reminders} from './ui/reminders'
|
|
||||||
import {reset as resetNavigation} from '../../Navigation'
|
import {reset as resetNavigation} from '../../Navigation'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
|
|
||||||
|
@ -53,7 +52,6 @@ export class RootStoreModel {
|
||||||
linkMetas = new LinkMetasCache(this)
|
linkMetas = new LinkMetasCache(this)
|
||||||
imageSizes = new ImageSizesCache()
|
imageSizes = new ImageSizesCache()
|
||||||
mutedThreads = new MutedThreads()
|
mutedThreads = new MutedThreads()
|
||||||
reminders = new Reminders(this)
|
|
||||||
|
|
||||||
constructor(agent: BskyAgent) {
|
constructor(agent: BskyAgent) {
|
||||||
this.agent = agent
|
this.agent = agent
|
||||||
|
@ -77,7 +75,6 @@ export class RootStoreModel {
|
||||||
preferences: this.preferences.serialize(),
|
preferences: this.preferences.serialize(),
|
||||||
invitedUsers: this.invitedUsers.serialize(),
|
invitedUsers: this.invitedUsers.serialize(),
|
||||||
mutedThreads: this.mutedThreads.serialize(),
|
mutedThreads: this.mutedThreads.serialize(),
|
||||||
reminders: this.reminders.serialize(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,9 +104,6 @@ export class RootStoreModel {
|
||||||
if (hasProp(v, 'mutedThreads')) {
|
if (hasProp(v, 'mutedThreads')) {
|
||||||
this.mutedThreads.hydrate(v.mutedThreads)
|
this.mutedThreads.hydrate(v.mutedThreads)
|
||||||
}
|
}
|
||||||
if (hasProp(v, 'reminders')) {
|
|
||||||
this.reminders.hydrate(v.reminders)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
import {makeAutoObservable} from 'mobx'
|
|
||||||
import {RootStoreModel} from '../root-store'
|
|
||||||
|
|
||||||
export class Reminders {
|
|
||||||
constructor(public rootStore: RootStoreModel) {
|
|
||||||
makeAutoObservable(
|
|
||||||
this,
|
|
||||||
{serialize: false, hydrate: false},
|
|
||||||
{autoBind: true},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
serialize() {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
|
|
||||||
hydrate(_v: unknown) {}
|
|
||||||
|
|
||||||
get shouldRequestEmailConfirmation() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
setEmailConfirmationRequested() {}
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
import {makeAutoObservable} from 'mobx'
|
|
||||||
import {isObj, hasProp} from 'lib/type-guards'
|
|
||||||
import {RootStoreModel} from '../root-store'
|
|
||||||
import {toHashCode} from 'lib/strings/helpers'
|
|
||||||
|
|
||||||
export class Reminders {
|
|
||||||
lastEmailConfirm: Date | null = null
|
|
||||||
|
|
||||||
constructor(public rootStore: RootStoreModel) {
|
|
||||||
makeAutoObservable(
|
|
||||||
this,
|
|
||||||
{serialize: false, hydrate: false},
|
|
||||||
{autoBind: true},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
serialize() {
|
|
||||||
return {
|
|
||||||
lastEmailConfirm: this.lastEmailConfirm
|
|
||||||
? this.lastEmailConfirm.toISOString()
|
|
||||||
: undefined,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hydrate(v: unknown) {
|
|
||||||
if (
|
|
||||||
isObj(v) &&
|
|
||||||
hasProp(v, 'lastEmailConfirm') &&
|
|
||||||
typeof v.lastEmailConfirm === 'string'
|
|
||||||
) {
|
|
||||||
this.lastEmailConfirm = new Date(v.lastEmailConfirm)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get shouldRequestEmailConfirmation() {
|
|
||||||
const sess = this.rootStore.session.currentSession
|
|
||||||
if (!sess) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (sess.emailConfirmed) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (this.rootStore.onboarding.isActive) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// only prompt once
|
|
||||||
if (this.lastEmailConfirm) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
const today = new Date()
|
|
||||||
// shard the users into 2 day of the week buckets
|
|
||||||
// (this is to avoid a sudden influx of email updates when
|
|
||||||
// this feature rolls out)
|
|
||||||
const code = toHashCode(sess.did) % 7
|
|
||||||
if (code !== today.getDay() && code !== (today.getDay() + 1) % 7) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
setEmailConfirmationRequested() {
|
|
||||||
this.lastEmailConfirm = new Date()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,6 +7,10 @@ import {ImageModel} from '../media/image'
|
||||||
import {ListModel} from '../content/list'
|
import {ListModel} from '../content/list'
|
||||||
import {GalleryModel} from '../media/gallery'
|
import {GalleryModel} from '../media/gallery'
|
||||||
import {StyleProp, ViewStyle} from 'react-native'
|
import {StyleProp, ViewStyle} from 'react-native'
|
||||||
|
import {
|
||||||
|
shouldRequestEmailConfirmation,
|
||||||
|
setEmailConfirmationRequested,
|
||||||
|
} from '#/state/shell/reminders'
|
||||||
|
|
||||||
export type ColorMode = 'system' | 'light' | 'dark'
|
export type ColorMode = 'system' | 'light' | 'dark'
|
||||||
|
|
||||||
|
@ -358,9 +362,14 @@ export class ShellUiModel {
|
||||||
|
|
||||||
setupLoginModals() {
|
setupLoginModals() {
|
||||||
this.rootStore.onSessionReady(() => {
|
this.rootStore.onSessionReady(() => {
|
||||||
if (this.rootStore.reminders.shouldRequestEmailConfirmation) {
|
if (
|
||||||
|
shouldRequestEmailConfirmation(
|
||||||
|
this.rootStore.session,
|
||||||
|
this.rootStore.onboarding,
|
||||||
|
)
|
||||||
|
) {
|
||||||
this.openModal({name: 'verify-email', showReminder: true})
|
this.openModal({name: 'verify-email', showReminder: true})
|
||||||
this.rootStore.reminders.setEmailConfirmationRequested()
|
setEmailConfirmationRequested()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,9 +76,9 @@ export function transform(legacy: LegacySchema): Schema {
|
||||||
defaults.session.currentAccount,
|
defaults.session.currentAccount,
|
||||||
},
|
},
|
||||||
reminders: {
|
reminders: {
|
||||||
lastEmailConfirmReminder:
|
lastEmailConfirm:
|
||||||
legacy.reminders.lastEmailConfirm ||
|
legacy.reminders.lastEmailConfirm ||
|
||||||
defaults.reminders.lastEmailConfirmReminder,
|
defaults.reminders.lastEmailConfirm,
|
||||||
},
|
},
|
||||||
languagePrefs: {
|
languagePrefs: {
|
||||||
primaryLanguage:
|
primaryLanguage:
|
||||||
|
|
|
@ -19,7 +19,7 @@ export const schema = z.object({
|
||||||
currentAccount: accountSchema.optional(),
|
currentAccount: accountSchema.optional(),
|
||||||
}),
|
}),
|
||||||
reminders: z.object({
|
reminders: z.object({
|
||||||
lastEmailConfirmReminder: z.string().optional(),
|
lastEmailConfirm: z.string().optional(),
|
||||||
}),
|
}),
|
||||||
languagePrefs: z.object({
|
languagePrefs: z.object({
|
||||||
primaryLanguage: z.string(), // should move to server
|
primaryLanguage: z.string(), // should move to server
|
||||||
|
@ -46,7 +46,7 @@ export const defaults: Schema = {
|
||||||
currentAccount: undefined,
|
currentAccount: undefined,
|
||||||
},
|
},
|
||||||
reminders: {
|
reminders: {
|
||||||
lastEmailConfirmReminder: undefined,
|
lastEmailConfirm: undefined,
|
||||||
},
|
},
|
||||||
languagePrefs: {
|
languagePrefs: {
|
||||||
primaryLanguage: deviceLocales[0] || 'en',
|
primaryLanguage: deviceLocales[0] || 'en',
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
import {OnboardingModel} from '../models/discovery/onboarding'
|
||||||
|
import {SessionModel} from '../models/session'
|
||||||
|
|
||||||
|
export function shouldRequestEmailConfirmation(
|
||||||
|
_session: SessionModel,
|
||||||
|
_onboarding: OnboardingModel,
|
||||||
|
) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setEmailConfirmationRequested() {}
|
|
@ -0,0 +1,40 @@
|
||||||
|
import * as persisted from '#/state/persisted'
|
||||||
|
import {OnboardingModel} from '../models/discovery/onboarding'
|
||||||
|
import {SessionModel} from '../models/session'
|
||||||
|
import {toHashCode} from 'lib/strings/helpers'
|
||||||
|
|
||||||
|
export function shouldRequestEmailConfirmation(
|
||||||
|
session: SessionModel,
|
||||||
|
onboarding: OnboardingModel,
|
||||||
|
) {
|
||||||
|
const sess = session.currentSession
|
||||||
|
if (!sess) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (sess.emailConfirmed) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (onboarding.isActive) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// only prompt once
|
||||||
|
if (persisted.get('reminders').lastEmailConfirm) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const today = new Date()
|
||||||
|
// shard the users into 2 day of the week buckets
|
||||||
|
// (this is to avoid a sudden influx of email updates when
|
||||||
|
// this feature rolls out)
|
||||||
|
const code = toHashCode(sess.did) % 7
|
||||||
|
if (code !== today.getDay() && code !== (today.getDay() + 1) % 7) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setEmailConfirmationRequested() {
|
||||||
|
persisted.write('reminders', {
|
||||||
|
...persisted.get('reminders'),
|
||||||
|
lastEmailConfirm: new Date().toISOString(),
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue