diff --git a/src/Navigation.tsx b/src/Navigation.tsx
index 4a55a43256..06f7ee3557 100644
--- a/src/Navigation.tsx
+++ b/src/Navigation.tsx
@@ -56,8 +56,8 @@ import {useModalControls} from './state/modals'
import {useUnreadNotifications} from './state/queries/notifications/unread'
import {useSession} from './state/session'
import {
- setEmailConfirmationRequested,
shouldRequestEmailConfirmation,
+ snoozeEmailConfirmationPrompt,
} from './state/shell/reminders'
import {AccessibilitySettingsScreen} from './view/screens/AccessibilitySettings'
import {CommunityGuidelinesScreen} from './view/screens/CommunityGuidelines'
@@ -597,7 +597,7 @@ function RoutesContainer({children}: React.PropsWithChildren<{}>) {
if (currentAccount && shouldRequestEmailConfirmation(currentAccount)) {
openModal({name: 'verify-email', showReminder: true})
- setEmailConfirmationRequested()
+ snoozeEmailConfirmationPrompt()
}
}
diff --git a/src/lib/strings/time.ts b/src/lib/strings/time.ts
index 1194e0240c..bfefea9bc3 100644
--- a/src/lib/strings/time.ts
+++ b/src/lib/strings/time.ts
@@ -19,3 +19,14 @@ export function getAge(birthDate: Date): number {
}
return age
}
+
+/**
+ * Compares two dates by year, month, and day only
+ */
+export function simpleAreDatesEqual(a: Date, b: Date): boolean {
+ return (
+ a.getFullYear() === b.getFullYear() &&
+ a.getMonth() === b.getMonth() &&
+ a.getDate() === b.getDate()
+ )
+}
diff --git a/src/screens/Profile/Header/ProfileHeaderLabeler.tsx b/src/screens/Profile/Header/ProfileHeaderLabeler.tsx
index 6588eb2e1d..d266decb32 100644
--- a/src/screens/Profile/Header/ProfileHeaderLabeler.tsx
+++ b/src/screens/Profile/Header/ProfileHeaderLabeler.tsx
@@ -82,7 +82,7 @@ let ProfileHeaderLabeler = ({
preferences?.moderationPrefs.labelers.find(l => l.did === profile.did)
const canSubscribe =
isSubscribed ||
- (preferences ? preferences?.moderationPrefs.labelers.length < 9 : false)
+ (preferences ? preferences?.moderationPrefs.labelers.length <= 20 : false)
const {mutateAsync: likeMod, isPending: isLikePending} = useLikeMutation()
const {mutateAsync: unlikeMod, isPending: isUnlikePending} =
useUnlikeMutation()
@@ -328,8 +328,8 @@ function CantSubscribePrompt({
Unable to subscribe
- We're sorry! You can only subscribe to ten labelers, and you've
- reached your limit of ten.
+ We're sorry! You can only subscribe to twenty labelers, and you've
+ reached your limit of twenty.
diff --git a/src/state/session/agent.ts b/src/state/session/agent.ts
index 48f5614bd8..6afb3af88c 100644
--- a/src/state/session/agent.ts
+++ b/src/state/session/agent.ts
@@ -11,6 +11,7 @@ import {
import {tryFetchGates} from '#/lib/statsig/statsig'
import {getAge} from '#/lib/strings/time'
import {logger} from '#/logger'
+import {snoozeEmailConfirmationPrompt} from '#/state/shell/reminders'
import {
configureModerationForAccount,
configureModerationForGuest,
@@ -191,6 +192,13 @@ export async function createAgentAndCreateAccount(
agent.setPersonalDetails({birthDate: birthDate.toISOString()})
}
+ try {
+ // snooze first prompt after signup, defer to next prompt
+ snoozeEmailConfirmationPrompt()
+ } catch (e: any) {
+ logger.error(e, {context: `session: failed snoozeEmailConfirmationPrompt`})
+ }
+
return prepareAgent(agent, gates, moderation, onSessionChange)
}
diff --git a/src/state/shell/reminders.e2e.ts b/src/state/shell/reminders.e2e.ts
index e8c12792ac..94809a680d 100644
--- a/src/state/shell/reminders.e2e.ts
+++ b/src/state/shell/reminders.e2e.ts
@@ -1,7 +1,5 @@
-export function init() {}
-
export function shouldRequestEmailConfirmation() {
return false
}
-export function setEmailConfirmationRequested() {}
+export function snoozeEmailConfirmationPrompt() {}
diff --git a/src/state/shell/reminders.ts b/src/state/shell/reminders.ts
index ee924eb001..db6ee9391b 100644
--- a/src/state/shell/reminders.ts
+++ b/src/state/shell/reminders.ts
@@ -1,36 +1,45 @@
+import {simpleAreDatesEqual} from '#/lib/strings/time'
+import {logger} from '#/logger'
import * as persisted from '#/state/persisted'
-import {toHashCode} from 'lib/strings/helpers'
-import {isOnboardingActive} from './onboarding'
import {SessionAccount} from '../session'
+import {isOnboardingActive} from './onboarding'
export function shouldRequestEmailConfirmation(account: SessionAccount) {
- if (!account) {
- return false
- }
- if (account.emailConfirmed) {
- return false
- }
- if (isOnboardingActive()) {
- return false
- }
- // only prompt once
- if (persisted.get('reminders').lastEmailConfirm) {
- return false
- }
+ // ignore logged out
+ if (!account) return false
+ // ignore confirmed accounts, this is the success state of this reminder
+ if (account.emailConfirmed) return false
+ // wait for onboarding to complete
+ if (isOnboardingActive()) return false
+
+ const snoozedAt = persisted.get('reminders').lastEmailConfirm
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(account.did) % 7
- if (code !== today.getDay() && code !== (today.getDay() + 1) % 7) {
+
+ logger.debug('Checking email confirmation reminder', {
+ today,
+ snoozedAt,
+ })
+
+ // never been snoozed, new account
+ if (!snoozedAt) {
+ return true
+ }
+
+ // already snoozed today
+ if (simpleAreDatesEqual(new Date(Date.parse(snoozedAt)), new Date())) {
return false
}
+
return true
}
-export function setEmailConfirmationRequested() {
+export function snoozeEmailConfirmationPrompt() {
+ const lastEmailConfirm = new Date().toISOString()
+ logger.debug('Snoozing email confirmation reminder', {
+ snoozedAt: lastEmailConfirm,
+ })
persisted.write('reminders', {
...persisted.get('reminders'),
- lastEmailConfirm: new Date().toISOString(),
+ lastEmailConfirm,
})
}