about summary refs log tree commit diff
path: root/src/state/persisted/legacy.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/state/persisted/legacy.ts')
-rw-r--r--src/state/persisted/legacy.ts137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/state/persisted/legacy.ts b/src/state/persisted/legacy.ts
new file mode 100644
index 000000000..6d0a2bccc
--- /dev/null
+++ b/src/state/persisted/legacy.ts
@@ -0,0 +1,137 @@
+import AsyncStorage from '@react-native-async-storage/async-storage'
+
+import {logger} from '#/logger'
+import {defaults, Schema} from '#/state/persisted/schema'
+import {write, read} from '#/state/persisted/store'
+
+/**
+ * The shape of the serialized data from our legacy Mobx store.
+ */
+type LegacySchema = {
+  shell: {
+    colorMode: 'system' | 'light' | 'dark'
+  }
+  session: {
+    data: {
+      service: string
+      did: `did:plc:${string}`
+    }
+    accounts: {
+      service: string
+      did: `did:plc:${string}`
+      refreshJwt: string
+      accessJwt: string
+      handle: string
+      email: string
+      displayName: string
+      aviUrl: string
+      emailConfirmed: boolean
+    }[]
+  }
+  me: {
+    did: `did:plc:${string}`
+    handle: string
+    displayName: string
+    description: string
+    avatar: string
+  }
+  onboarding: {
+    step: string
+  }
+  preferences: {
+    primaryLanguage: string
+    contentLanguages: string[]
+    postLanguage: string
+    postLanguageHistory: string[]
+    contentLabels: {
+      nsfw: string
+      nudity: string
+      suggestive: string
+      gore: string
+      hate: string
+      spam: string
+      impersonation: string
+    }
+    savedFeeds: string[]
+    pinnedFeeds: string[]
+    requireAltTextEnabled: boolean
+  }
+  invitedUsers: {
+    seenDids: string[]
+    copiedInvites: string[]
+  }
+  mutedThreads: {uris: string[]}
+  reminders: {lastEmailConfirm: string}
+}
+
+const DEPRECATED_ROOT_STATE_STORAGE_KEY = 'root'
+
+export function transform(legacy: LegacySchema): Schema {
+  return {
+    colorMode: legacy.shell?.colorMode || defaults.colorMode,
+    session: {
+      accounts: legacy.session.accounts || defaults.session.accounts,
+      currentAccount:
+        legacy.session.accounts.find(a => a.did === legacy.session.data.did) ||
+        defaults.session.currentAccount,
+    },
+    reminders: {
+      lastEmailConfirmReminder:
+        legacy.reminders.lastEmailConfirm ||
+        defaults.reminders.lastEmailConfirmReminder,
+    },
+    languagePrefs: {
+      primaryLanguage:
+        legacy.preferences.primaryLanguage ||
+        defaults.languagePrefs.primaryLanguage,
+      contentLanguages:
+        legacy.preferences.contentLanguages ||
+        defaults.languagePrefs.contentLanguages,
+      postLanguage:
+        legacy.preferences.postLanguage || defaults.languagePrefs.postLanguage,
+      postLanguageHistory:
+        legacy.preferences.postLanguageHistory ||
+        defaults.languagePrefs.postLanguageHistory,
+    },
+    requireAltTextEnabled:
+      legacy.preferences.requireAltTextEnabled ||
+      defaults.requireAltTextEnabled,
+    mutedThreads: legacy.mutedThreads.uris || defaults.mutedThreads,
+    invitedUsers: {
+      seenDids: legacy.invitedUsers.seenDids || defaults.invitedUsers.seenDids,
+      copiedInvites:
+        legacy.invitedUsers.copiedInvites ||
+        defaults.invitedUsers.copiedInvites,
+    },
+    onboarding: {
+      step: legacy.onboarding.step || defaults.onboarding.step,
+    },
+  }
+}
+
+/**
+ * Migrates legacy persisted state to new store if new store doesn't exist in
+ * local storage AND old storage exists.
+ */
+export async function migrate() {
+  logger.debug('persisted state: migrate')
+
+  try {
+    const rawLegacyData = await AsyncStorage.getItem(
+      DEPRECATED_ROOT_STATE_STORAGE_KEY,
+    )
+    const alreadyMigrated = Boolean(await read())
+
+    if (!alreadyMigrated && rawLegacyData) {
+      logger.debug('persisted state: migrating legacy storage')
+      const legacyData = JSON.parse(rawLegacyData)
+      const newData = transform(legacyData)
+      await write(newData)
+      logger.debug('persisted state: migrated legacy storage')
+    }
+  } catch (e) {
+    logger.error('persisted state: error migrating legacy storage', {
+      error: String(e),
+    })
+  }
+}