mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import '#/lib/sentry' // must be near top
2import '#/view/icons'
3import './style.css'
4
5import React, {useEffect, useState} from 'react'
6import {KeyboardProvider} from 'react-native-keyboard-controller'
7import {RootSiblingParent} from 'react-native-root-siblings'
8import {SafeAreaProvider} from 'react-native-safe-area-context'
9import {msg} from '@lingui/macro'
10import {useLingui} from '@lingui/react'
11
12import {QueryProvider} from '#/lib/react-query'
13import {Provider as StatsigProvider} from '#/lib/statsig/statsig'
14import {ThemeProvider} from '#/lib/ThemeContext'
15import I18nProvider from '#/locale/i18nProvider'
16import {logger} from '#/logger'
17import {Provider as A11yProvider} from '#/state/a11y'
18import {Provider as MutedThreadsProvider} from '#/state/cache/thread-mutes'
19import {Provider as DialogStateProvider} from '#/state/dialogs'
20import {listenSessionDropped} from '#/state/events'
21import {
22 beginResolveGeolocation,
23 ensureGeolocationResolved,
24 Provider as GeolocationProvider,
25} from '#/state/geolocation'
26import {Provider as InvitesStateProvider} from '#/state/invites'
27import {Provider as LightboxStateProvider} from '#/state/lightbox'
28import {MessagesProvider} from '#/state/messages'
29import {Provider as ModalStateProvider} from '#/state/modals'
30import {init as initPersistedState} from '#/state/persisted'
31import {Provider as PrefsStateProvider} from '#/state/preferences'
32import {Provider as LabelDefsProvider} from '#/state/preferences/label-defs'
33import {Provider as ModerationOptsProvider} from '#/state/preferences/moderation-opts'
34import {Provider as UnreadNotifsProvider} from '#/state/queries/notifications/unread'
35import {
36 Provider as SessionProvider,
37 SessionAccount,
38 useSession,
39 useSessionApi,
40} from '#/state/session'
41import {readLastActiveAccount} from '#/state/session/util'
42import {Provider as ShellStateProvider} from '#/state/shell'
43import {Provider as ComposerProvider} from '#/state/shell/composer'
44import {Provider as LoggedOutViewProvider} from '#/state/shell/logged-out'
45import {Provider as ProgressGuideProvider} from '#/state/shell/progress-guide'
46import {Provider as SelectedFeedProvider} from '#/state/shell/selected-feed'
47import {Provider as StarterPackProvider} from '#/state/shell/starter-pack'
48import {Provider as HiddenRepliesProvider} from '#/state/threadgate-hidden-replies'
49import {Provider as ActiveVideoProvider} from '#/view/com/util/post-embeds/ActiveVideoWebContext'
50import {Provider as VideoVolumeProvider} from '#/view/com/util/post-embeds/VideoVolumeContext'
51import * as Toast from '#/view/com/util/Toast'
52import {ToastContainer} from '#/view/com/util/Toast.web'
53import {Shell} from '#/view/shell/index'
54import {ThemeProvider as Alf} from '#/alf'
55import {useColorModeTheme} from '#/alf/util/useColorModeTheme'
56import {NuxDialogs} from '#/components/dialogs/nuxs'
57import {useStarterPackEntry} from '#/components/hooks/useStarterPackEntry'
58import {Provider as IntentDialogProvider} from '#/components/intents/IntentDialogs'
59import {Provider as PortalProvider} from '#/components/Portal'
60import {BackgroundNotificationPreferencesProvider} from '../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider'
61
62/**
63 * Begin geolocation ASAP
64 */
65beginResolveGeolocation()
66
67function InnerApp() {
68 const [isReady, setIsReady] = React.useState(false)
69 const {currentAccount} = useSession()
70 const {resumeSession} = useSessionApi()
71 const theme = useColorModeTheme()
72 const {_} = useLingui()
73 const hasCheckedReferrer = useStarterPackEntry()
74
75 // init
76 useEffect(() => {
77 async function onLaunch(account?: SessionAccount) {
78 try {
79 if (account) {
80 await resumeSession(account)
81 }
82 } catch (e) {
83 logger.error(`session: resumeSession failed`, {message: e})
84 } finally {
85 setIsReady(true)
86 }
87 }
88 const account = readLastActiveAccount()
89 onLaunch(account)
90 }, [resumeSession])
91
92 useEffect(() => {
93 return listenSessionDropped(() => {
94 Toast.show(
95 _(msg`Sorry! Your session expired. Please log in again.`),
96 'info',
97 )
98 })
99 }, [_])
100
101 // wait for session to resume
102 if (!isReady || !hasCheckedReferrer) return null
103
104 return (
105 <KeyboardProvider enabled={false}>
106 <Alf theme={theme}>
107 <ThemeProvider theme={theme}>
108 <RootSiblingParent>
109 <VideoVolumeProvider>
110 <ActiveVideoProvider>
111 <React.Fragment
112 // Resets the entire tree below when it changes:
113 key={currentAccount?.did}>
114 <QueryProvider currentDid={currentAccount?.did}>
115 <ComposerProvider>
116 <StatsigProvider>
117 <MessagesProvider>
118 {/* LabelDefsProvider MUST come before ModerationOptsProvider */}
119 <LabelDefsProvider>
120 <ModerationOptsProvider>
121 <LoggedOutViewProvider>
122 <SelectedFeedProvider>
123 <HiddenRepliesProvider>
124 <UnreadNotifsProvider>
125 <BackgroundNotificationPreferencesProvider>
126 <MutedThreadsProvider>
127 <SafeAreaProvider>
128 <ProgressGuideProvider>
129 <Shell />
130 <NuxDialogs />
131 </ProgressGuideProvider>
132 </SafeAreaProvider>
133 </MutedThreadsProvider>
134 </BackgroundNotificationPreferencesProvider>
135 </UnreadNotifsProvider>
136 </HiddenRepliesProvider>
137 </SelectedFeedProvider>
138 </LoggedOutViewProvider>
139 </ModerationOptsProvider>
140 </LabelDefsProvider>
141 </MessagesProvider>
142 </StatsigProvider>
143 </ComposerProvider>
144 </QueryProvider>
145 <ToastContainer />
146 </React.Fragment>
147 </ActiveVideoProvider>
148 </VideoVolumeProvider>
149 </RootSiblingParent>
150 </ThemeProvider>
151 </Alf>
152 </KeyboardProvider>
153 )
154}
155
156function App() {
157 const [isReady, setReady] = useState(false)
158
159 React.useEffect(() => {
160 Promise.all([initPersistedState(), ensureGeolocationResolved()]).then(() =>
161 setReady(true),
162 )
163 }, [])
164
165 if (!isReady) {
166 return null
167 }
168
169 /*
170 * NOTE: only nothing here can depend on other data or session state, since
171 * that is set up in the InnerApp component above.
172 */
173 return (
174 <GeolocationProvider>
175 <A11yProvider>
176 <SessionProvider>
177 <PrefsStateProvider>
178 <I18nProvider>
179 <ShellStateProvider>
180 <InvitesStateProvider>
181 <ModalStateProvider>
182 <DialogStateProvider>
183 <LightboxStateProvider>
184 <PortalProvider>
185 <StarterPackProvider>
186 <IntentDialogProvider>
187 <InnerApp />
188 </IntentDialogProvider>
189 </StarterPackProvider>
190 </PortalProvider>
191 </LightboxStateProvider>
192 </DialogStateProvider>
193 </ModalStateProvider>
194 </InvitesStateProvider>
195 </ShellStateProvider>
196 </I18nProvider>
197 </PrefsStateProvider>
198 </SessionProvider>
199 </A11yProvider>
200 </GeolocationProvider>
201 )
202}
203
204export default App