about summary refs log tree commit diff
path: root/src/state/models/root-store.ts
blob: d1e73132874653cea67723598b6675564443a02b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/**
 * The root store is the base of all modeled state.
 */

import {makeAutoObservable} from 'mobx'
import {adx, AdxClient} from '@adxp/mock-api'
import {createContext, useContext} from 'react'
import {isObj, hasProp} from '../lib/type-guards'
import {SessionModel} from './session'
import {NavigationModel} from './navigation'
import {MeModel} from './me'
import {FeedViewModel} from './feed-view'
import {NotificationsViewModel} from './notifications-view'

export class RootStoreModel {
  session = new SessionModel()
  nav = new NavigationModel()
  me = new MeModel(this)
  homeFeed = new FeedViewModel(this, {})
  notesFeed = new NotificationsViewModel(this, {})

  constructor(public api: AdxClient) {
    makeAutoObservable(this, {
      api: false,
      resolveName: false,
      serialize: false,
      hydrate: false,
    })
  }

  async resolveName(didOrName: string) {
    const userDb = this.api.mockDb.getUser(didOrName)
    if (!userDb) throw new Error(`User not found: ${didOrName}`)
    return userDb.did
  }

  serialize(): unknown {
    return {
      session: this.session.serialize(),
      nav: this.nav.serialize(),
    }
  }

  hydrate(v: unknown) {
    if (isObj(v)) {
      if (hasProp(v, 'session')) {
        this.session.hydrate(v.session)
      }
      if (hasProp(v, 'nav')) {
        this.nav.hydrate(v.nav)
      }
    }
  }
}

const throwawayInst = new RootStoreModel(adx) // this will be replaced by the loader
const RootStoreContext = createContext<RootStoreModel>(throwawayInst)
export const RootStoreProvider = RootStoreContext.Provider
export const useStores = () => useContext(RootStoreContext)