summaryrefslogtreecommitdiff
path: root/app_expo/models/root-store
diff options
context:
space:
mode:
Diffstat (limited to 'app_expo/models/root-store')
-rw-r--r--app_expo/models/root-store/root-store-context.ts22
-rw-r--r--app_expo/models/root-store/root-store.ts20
-rw-r--r--app_expo/models/root-store/setup-root-store.ts55
3 files changed, 97 insertions, 0 deletions
diff --git a/app_expo/models/root-store/root-store-context.ts b/app_expo/models/root-store/root-store-context.ts
new file mode 100644
index 0000000..f01a35c
--- /dev/null
+++ b/app_expo/models/root-store/root-store-context.ts
@@ -0,0 +1,22 @@
+import { createContext, useContext } from 'react'
+import { RootStore } from './root-store'
+
+/**
+ * Create a context we can use to
+ * - Provide access to our stores from our root component
+ * - Consume stores in our screens (or other components, though it's
+ * preferable to just connect screens)
+ */
+const RootStoreContext = createContext<RootStore>({} as RootStore)
+
+/**
+ * The provider our root component will use to expose the root store
+ */
+export const RootStoreProvider = RootStoreContext.Provider
+
+/**
+ * A hook that screens can use to gain access to our stores, with
+ * `const { someStore, someOtherStore } = useStores()`,
+ * or less likely: `const rootStore = useStores()`
+ */
+export const useStores = () => useContext(RootStoreContext)
diff --git a/app_expo/models/root-store/root-store.ts b/app_expo/models/root-store/root-store.ts
new file mode 100644
index 0000000..56425bc
--- /dev/null
+++ b/app_expo/models/root-store/root-store.ts
@@ -0,0 +1,20 @@
+import { Instance, SnapshotOut, types } from 'mobx-state-tree'
+import { CharacterStoreModel } from '../character-store/character-store'
+
+/**
+ * A RootStore model.
+ */
+// prettier-ignore
+export const RootStoreModel = types.model("RootStore").props({
+ characterStore: types.optional(CharacterStoreModel, {} as any),
+})
+
+/**
+ * The RootStore instance.
+ */
+export interface RootStore extends Instance<typeof RootStoreModel> {}
+
+/**
+ * The data of a RootStore.
+ */
+export interface RootStoreSnapshot extends SnapshotOut<typeof RootStoreModel> {}
diff --git a/app_expo/models/root-store/setup-root-store.ts b/app_expo/models/root-store/setup-root-store.ts
new file mode 100644
index 0000000..40e3ad8
--- /dev/null
+++ b/app_expo/models/root-store/setup-root-store.ts
@@ -0,0 +1,55 @@
+import { onSnapshot } from 'mobx-state-tree'
+import { RootStoreModel, RootStore } from './root-store'
+import { Environment } from '../environment'
+import * as storage from '../../utils/storage'
+
+/**
+ * The key we'll be saving our state as within async storage.
+ */
+const ROOT_STATE_STORAGE_KEY = 'root'
+
+/**
+ * Setup the environment that all the models will be sharing.
+ *
+ * The environment includes other functions that will be picked from some
+ * of the models that get created later. This is how we loosly couple things
+ * like events between models.
+ */
+export async function createEnvironment() {
+ const env = new Environment()
+ await env.setup()
+ return env
+}
+
+/**
+ * Setup the root state.
+ */
+export async function setupRootStore() {
+ let rootStore: RootStore
+ let data: any
+
+ // prepare the environment that will be associated with the RootStore.
+ const env = await createEnvironment()
+ try {
+ // load data from storage
+ data = (await storage.load(ROOT_STATE_STORAGE_KEY)) || {}
+ rootStore = RootStoreModel.create(data, env)
+ } catch (e) {
+ // if there's any problems loading, then let's at least fallback to an empty state
+ // instead of crashing.
+ rootStore = RootStoreModel.create({}, env)
+
+ // but please inform us what happened
+ __DEV__ && console.tron.error(e.message, null)
+ }
+
+ // reactotron logging
+ if (__DEV__) {
+ env.reactotron.setRootStore(rootStore, data)
+ }
+
+ // track changes & save to storage
+ onSnapshot(rootStore, (snapshot) => storage.save(ROOT_STATE_STORAGE_KEY, snapshot))
+
+ return rootStore
+}