diff options
-rw-r--r-- | src/state/persisted/__tests__/legacy.test.ts | 13 | ||||
-rw-r--r-- | src/state/persisted/index.ts | 5 | ||||
-rw-r--r-- | src/state/persisted/legacy.ts | 33 | ||||
-rw-r--r-- | src/state/persisted/schema.ts | 7 | ||||
-rw-r--r-- | src/state/session/index.tsx | 4 | ||||
-rw-r--r-- | src/view/com/modals/ChangeEmail.tsx | 4 | ||||
-rw-r--r-- | src/view/com/modals/VerifyEmail.tsx | 6 | ||||
-rw-r--r-- | src/view/screens/Settings.tsx | 2 | ||||
-rw-r--r-- | src/view/shell/desktop/RightNav.tsx | 4 |
9 files changed, 48 insertions, 30 deletions
diff --git a/src/state/persisted/__tests__/legacy.test.ts b/src/state/persisted/__tests__/legacy.test.ts new file mode 100644 index 000000000..7f4b138a1 --- /dev/null +++ b/src/state/persisted/__tests__/legacy.test.ts @@ -0,0 +1,13 @@ +import {expect, test} from '@jest/globals' + +import {transform} from '#/state/persisted/legacy' +import {defaults, schema} from '#/state/persisted/schema' + +test('defaults', () => { + expect(() => schema.parse(defaults)).not.toThrow() +}) + +test('transform', () => { + const data = transform({}) + expect(() => schema.parse(data)).not.toThrow() +}) diff --git a/src/state/persisted/index.ts b/src/state/persisted/index.ts index 545fdc0e1..67d8b78c6 100644 --- a/src/state/persisted/index.ts +++ b/src/state/persisted/index.ts @@ -26,7 +26,10 @@ export async function init() { try { await migrate() // migrate old store const stored = await store.read() // check for new store - if (!stored) await store.write(defaults) // opt: init new store + if (!stored) { + logger.info('persisted state: initializing default storage') + await store.write(defaults) // opt: init new store + } _state = stored || defaults // return new store logger.log('persisted state: initialized') } catch (e) { diff --git a/src/state/persisted/legacy.ts b/src/state/persisted/legacy.ts index 025877529..c45b18322 100644 --- a/src/state/persisted/legacy.ts +++ b/src/state/persisted/legacy.ts @@ -1,7 +1,7 @@ import AsyncStorage from '@react-native-async-storage/async-storage' import {logger} from '#/logger' -import {defaults, Schema} from '#/state/persisted/schema' +import {defaults, Schema, schema} from '#/state/persisted/schema' import {write, read} from '#/state/persisted/store' /** @@ -66,7 +66,6 @@ type LegacySchema = { const DEPRECATED_ROOT_STATE_STORAGE_KEY = 'root' -// TODO remove, assume that partial data may be here during our refactor export function transform(legacy: Partial<LegacySchema>): Schema { return { colorMode: legacy.shell?.colorMode || defaults.colorMode, @@ -116,7 +115,7 @@ export function transform(legacy: Partial<LegacySchema>): Schema { * local storage AND old storage exists. */ export async function migrate() { - logger.info('persisted state: migrate') + logger.info('persisted state: check need to migrate') try { const rawLegacyData = await AsyncStorage.getItem( @@ -138,6 +137,7 @@ export async function migrate() { ), }) logger.info(`persisted state: debug new data`, { + hasNewData: Boolean(newData), hasExistingLoggedInAccount: Boolean(newData?.session?.currentAccount), numberOfExistingAccounts: newData?.session?.accounts?.length, existingAccountMatchesLegacy: Boolean( @@ -145,27 +145,32 @@ export async function migrate() { legacy?.session?.data?.did, ), }) - } else { - logger.info(`persisted state: no legacy to debug, fresh install`) } - } catch (e) { - logger.error(`persisted state: legacy debugging failed`, {error: e}) + } catch (e: any) { + logger.error(e, {message: `persisted state: legacy debugging failed`}) } if (!alreadyMigrated && rawLegacyData) { logger.info('persisted state: migrating legacy storage') + const legacyData = JSON.parse(rawLegacyData) const newData = transform(legacyData) - await write(newData) - // track successful migrations - logger.log('persisted state: migrated legacy storage') + const validate = schema.safeParse(newData) + + if (validate.success) { + await write(newData) + logger.log('persisted state: migrated legacy storage') + } else { + logger.error('persisted state: legacy data failed validation', { + error: validate.error, + }) + } } else { - // track successful migrations logger.log('persisted state: no migration needed') } - } catch (e) { - logger.error('persisted state: error migrating legacy storage', { - error: String(e), + } catch (e: any) { + logger.error(e, { + message: 'persisted state: error migrating legacy storage', }) } } diff --git a/src/state/persisted/schema.ts b/src/state/persisted/schema.ts index 71f9bd545..5ed8e01f3 100644 --- a/src/state/persisted/schema.ts +++ b/src/state/persisted/schema.ts @@ -2,17 +2,14 @@ import {z} from 'zod' import {deviceLocales} from '#/platform/detection' // only data needed for rendering account page -// TODO agent.resumeSession requires the following fields const accountSchema = z.object({ service: z.string(), did: z.string(), handle: z.string(), - email: z.string(), - emailConfirmed: z.boolean(), + email: z.string().optional(), + emailConfirmed: z.boolean().optional(), refreshJwt: z.string().optional(), // optional because it can expire accessJwt: z.string().optional(), // optional because it can expire - // displayName: z.string().optional(), - // aviUrl: z.string().optional(), }) export type PersistedAccount = z.infer<typeof accountSchema> diff --git a/src/state/session/index.tsx b/src/state/session/index.tsx index e6def1fab..37454187a 100644 --- a/src/state/session/index.tsx +++ b/src/state/session/index.tsx @@ -245,7 +245,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) { service: agent.service.toString(), did: agent.session.did, handle: agent.session.handle, - email: agent.session.email!, // TODO this is always defined? + email: agent.session.email, emailConfirmed: agent.session.emailConfirmed || false, refreshJwt: agent.session.refreshJwt, accessJwt: agent.session.accessJwt, @@ -342,7 +342,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) { service: agent.service.toString(), did: agent.session.did, handle: agent.session.handle, - email: agent.session.email!, // TODO this is always defined? + email: agent.session.email, emailConfirmed: agent.session.emailConfirmed || false, refreshJwt: agent.session.refreshJwt, accessJwt: agent.session.accessJwt, diff --git a/src/view/com/modals/ChangeEmail.tsx b/src/view/com/modals/ChangeEmail.tsx index 73ab33dd4..44b102fa0 100644 --- a/src/view/com/modals/ChangeEmail.tsx +++ b/src/view/com/modals/ChangeEmail.tsx @@ -118,8 +118,8 @@ export function Component() { ) : stage === Stages.ConfirmCode ? ( <Trans> An email has been sent to your previous address,{' '} - {currentAccount?.email || ''}. It includes a confirmation code - which you can enter below. + {currentAccount?.email || '(no email)'}. It includes a + confirmation code which you can enter below. </Trans> ) : ( <Trans> diff --git a/src/view/com/modals/VerifyEmail.tsx b/src/view/com/modals/VerifyEmail.tsx index 4376a3e45..786a814a7 100644 --- a/src/view/com/modals/VerifyEmail.tsx +++ b/src/view/com/modals/VerifyEmail.tsx @@ -108,8 +108,8 @@ export function Component({showReminder}: {showReminder?: boolean}) { </Trans> ) : stage === Stages.ConfirmCode ? ( <Trans> - An email has been sent to {currentAccount?.email || ''}. It - includes a confirmation code which you can enter below. + An email has been sent to {currentAccount?.email || '(no email)'}. + It includes a confirmation code which you can enter below. </Trans> ) : ( '' @@ -125,7 +125,7 @@ export function Component({showReminder}: {showReminder?: boolean}) { size={16} /> <Text type="xl-medium" style={[pal.text, s.flex1, {minWidth: 0}]}> - {currentAccount?.email || ''} + {currentAccount?.email || '(no email)'} </Text> </View> <Pressable diff --git a/src/view/screens/Settings.tsx b/src/view/screens/Settings.tsx index 388a5d954..b7ba32b0d 100644 --- a/src/view/screens/Settings.tsx +++ b/src/view/screens/Settings.tsx @@ -299,7 +299,7 @@ export function SettingsScreen({}: Props) { </> )} <Text type="lg" style={pal.text}> - {currentAccount.email}{' '} + {currentAccount.email || '(no email)'}{' '} </Text> <Link onPress={() => openModal({name: 'change-email'})}> <Text type="lg" style={pal.link}> diff --git a/src/view/shell/desktop/RightNav.tsx b/src/view/shell/desktop/RightNav.tsx index 9a5186549..c8196c2c4 100644 --- a/src/view/shell/desktop/RightNav.tsx +++ b/src/view/shell/desktop/RightNav.tsx @@ -58,8 +58,8 @@ export function DesktopRightNav() { type="md" style={pal.link} href={FEEDBACK_FORM_URL({ - email: currentAccount!.email, - handle: currentAccount!.handle, + email: currentAccount?.email, + handle: currentAccount?.handle, })} text={_(msg`Feedback`)} /> |