about summary refs log tree commit diff
path: root/src/App.web.tsx
blob: f47f763da160e384b24d5acc39ea190fa3a3b743 (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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import 'lib/sentry' // must be near top

import React, {useState, useEffect} from 'react'
import {PersistQueryClientProvider} from '@tanstack/react-query-persist-client'
import {SafeAreaProvider} from 'react-native-safe-area-context'
import {RootSiblingParent} from 'react-native-root-siblings'

import 'view/icons'

import {ThemeProvider as Alf} from '#/alf'
import {useColorModeTheme} from '#/alf/util/useColorModeTheme'
import {init as initPersistedState} from '#/state/persisted'
import {Shell} from 'view/shell/index'
import {ToastContainer} from 'view/com/util/Toast.web'
import {ThemeProvider} from 'lib/ThemeContext'
import {
  queryClient,
  asyncStoragePersister,
  dehydrateOptions,
} from 'lib/react-query'
import {Provider as ShellStateProvider} from 'state/shell'
import {Provider as ModalStateProvider} from 'state/modals'
import {Provider as DialogStateProvider} from 'state/dialogs'
import {Provider as LightboxStateProvider} from 'state/lightbox'
import {Provider as MutedThreadsProvider} from 'state/muted-threads'
import {Provider as InvitesStateProvider} from 'state/invites'
import {Provider as PrefsStateProvider} from 'state/preferences'
import {Provider as LoggedOutViewProvider} from 'state/shell/logged-out'
import {Provider as SelectedFeedProvider} from 'state/shell/selected-feed'
import {Provider as LabelDefsProvider} from '#/state/preferences/label-defs'
import I18nProvider from './locale/i18nProvider'
import {
  Provider as SessionProvider,
  useSession,
  useSessionApi,
} from 'state/session'
import {Provider as UnreadNotifsProvider} from 'state/queries/notifications/unread'
import * as persisted from '#/state/persisted'
import {Provider as PortalProvider} from '#/components/Portal'
import {Provider as StatsigProvider} from '#/lib/statsig/statsig'
import {useIntentHandler} from 'lib/hooks/useIntentHandler'

function InnerApp() {
  const {isInitialLoad, currentAccount} = useSession()
  const {resumeSession} = useSessionApi()
  const theme = useColorModeTheme()
  useIntentHandler()

  // init
  useEffect(() => {
    const account = persisted.get('session').currentAccount
    resumeSession(account)
  }, [resumeSession])

  // wait for session to resume
  if (isInitialLoad) return null

  return (
    <Alf theme={theme}>
      <React.Fragment
        // Resets the entire tree below when it changes:
        key={currentAccount?.did}>
        <StatsigProvider>
          <LabelDefsProvider>
            <LoggedOutViewProvider>
              <SelectedFeedProvider>
                <UnreadNotifsProvider>
                  <ThemeProvider theme={theme}>
                    {/* All components should be within this provider */}
                    <RootSiblingParent>
                      <SafeAreaProvider>
                        <Shell />
                      </SafeAreaProvider>
                    </RootSiblingParent>
                    <ToastContainer />
                  </ThemeProvider>
                </UnreadNotifsProvider>
              </SelectedFeedProvider>
            </LoggedOutViewProvider>
          </LabelDefsProvider>
        </StatsigProvider>
      </React.Fragment>
    </Alf>
  )
}

function App() {
  const [isReady, setReady] = useState(false)

  React.useEffect(() => {
    initPersistedState().then(() => setReady(true))
  }, [])

  if (!isReady) {
    return null
  }

  /*
   * NOTE: only nothing here can depend on other data or session state, since
   * that is set up in the InnerApp component above.
   */
  return (
    <PersistQueryClientProvider
      client={queryClient}
      persistOptions={{persister: asyncStoragePersister, dehydrateOptions}}>
      <SessionProvider>
        <ShellStateProvider>
          <PrefsStateProvider>
            <MutedThreadsProvider>
              <InvitesStateProvider>
                <ModalStateProvider>
                  <DialogStateProvider>
                    <LightboxStateProvider>
                      <I18nProvider>
                        <PortalProvider>
                          <InnerApp />
                        </PortalProvider>
                      </I18nProvider>
                    </LightboxStateProvider>
                  </DialogStateProvider>
                </ModalStateProvider>
              </InvitesStateProvider>
            </MutedThreadsProvider>
          </PrefsStateProvider>
        </ShellStateProvider>
      </SessionProvider>
    </PersistQueryClientProvider>
  )
}

export default App