this repo has no description
1import '#/logger/sentry/setup' // must be near top
2import '#/view/icons'
3import './style.css'
4
5import {Fragment, useEffect, useState} from 'react'
6import {KeyboardProvider as KeyboardControllerProvider} from 'react-native-keyboard-controller'
7import {SafeAreaProvider} from 'react-native-safe-area-context'
8import {msg} from '@lingui/core/macro'
9import {useLingui} from '@lingui/react'
10import * as Sentry from '@sentry/react-native'
11
12import {QueryProvider} from '#/lib/react-query'
13import {ThemeProvider} from '#/lib/ThemeContext'
14import {Provider as TranslateOnDeviceProvider} from '#/lib/translation'
15import I18nProvider from '#/locale/i18nProvider'
16import {logger} from '#/logger'
17import {Provider as A11yProvider} from '#/state/a11y'
18import {
19 prefetchAppConfig,
20 Provider as AppConfigProvider,
21} from '#/state/appConfig'
22import {Provider as MutedThreadsProvider} from '#/state/cache/thread-mutes'
23import {Provider as DialogStateProvider} from '#/state/dialogs'
24import {Provider as EmailVerificationProvider} from '#/state/email-verification'
25import {listenSessionDropped} from '#/state/events'
26import {Provider as HomeBadgeProvider} from '#/state/home-badge'
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 {Provider as ServiceConfigProvider} from '#/state/service-config'
36import {
37 Provider as SessionProvider,
38 type SessionAccount,
39 useSession,
40 useSessionApi,
41} from '#/state/session'
42import {readLastActiveAccount} from '#/state/session/util'
43import {Provider as ShellStateProvider} from '#/state/shell'
44import {Provider as ComposerProvider} from '#/state/shell/composer'
45import {Provider as LoggedOutViewProvider} from '#/state/shell/logged-out'
46import {Provider as OnboardingProvider} from '#/state/shell/onboarding'
47import {Provider as ProgressGuideProvider} from '#/state/shell/progress-guide'
48import {Provider as SelectedFeedProvider} from '#/state/shell/selected-feed'
49import {Provider as StarterPackProvider} from '#/state/shell/starter-pack'
50import {Provider as HiddenRepliesProvider} from '#/state/threadgate-hidden-replies'
51import {Shell} from '#/view/shell/index'
52import {ThemeProvider as Alf} from '#/alf'
53import {useColorModeTheme} from '#/alf/util/useColorModeTheme'
54import {Provider as ContextMenuProvider} from '#/components/ContextMenu'
55import {useStarterPackEntry} from '#/components/hooks/useStarterPackEntry'
56import {Provider as IntentDialogProvider} from '#/components/intents/IntentDialogs'
57import {Provider as PolicyUpdateOverlayProvider} from '#/components/PolicyUpdateOverlay'
58import {Provider as PortalProvider} from '#/components/Portal'
59import {Provider as ActiveVideoProvider} from '#/components/Post/Embed/VideoEmbed/ActiveVideoWebContext'
60import {Provider as VideoVolumeProvider} from '#/components/Post/Embed/VideoEmbed/VideoVolumeContext'
61import * as Toast from '#/components/Toast'
62import {ToastOutlet} from '#/components/Toast'
63import {
64 prefetchAgeAssuranceConfig,
65 Provider as AgeAssuranceV2Provider,
66} from '#/ageAssurance'
67import {
68 AnalyticsContext,
69 AnalyticsFeaturesContext,
70 features,
71 setupDeviceId,
72} from '#/analytics'
73import {
74 prefetchLiveEvents,
75 Provider as LiveEventsProvider,
76} from '#/features/liveEvents/context'
77import * as Geo from '#/geolocation'
78import {Splash} from '#/Splash'
79import {BackgroundNotificationPreferencesProvider} from '../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider'
80import {Provider as HideBottomBarBorderProvider} from './lib/hooks/useHideBottomBarBorder'
81
82/**
83 * Begin geolocation ASAP
84 */
85Geo.resolve()
86prefetchAgeAssuranceConfig()
87prefetchLiveEvents()
88prefetchAppConfig()
89
90function InnerApp() {
91 const [isReady, setIsReady] = useState(false)
92 const {currentAccount} = useSession()
93 const {resumeSession} = useSessionApi()
94 const theme = useColorModeTheme()
95 const {_} = useLingui()
96 const hasCheckedReferrer = useStarterPackEntry()
97
98 // init
99 useEffect(() => {
100 async function onLaunch(account?: SessionAccount) {
101 try {
102 if (account) {
103 await resumeSession(account)
104 } else {
105 await features.init
106 }
107 } catch (e) {
108 logger.error(`session: resumeSession failed`, {message: e})
109 } finally {
110 setIsReady(true)
111 }
112 }
113 const account = readLastActiveAccount()
114 onLaunch(account)
115 }, [resumeSession])
116
117 useEffect(() => {
118 return listenSessionDropped(() => {
119 Toast.show(_(msg`Sorry! Your session expired. Please sign in again.`), {
120 type: 'info',
121 })
122 })
123 }, [_])
124
125 return (
126 <Alf theme={theme}>
127 <ThemeProvider theme={theme}>
128 <ContextMenuProvider>
129 <Splash isReady={isReady && hasCheckedReferrer}>
130 <VideoVolumeProvider>
131 <ActiveVideoProvider>
132 <Fragment
133 // Resets the entire tree below when it changes:
134 key={currentAccount?.did}>
135 <AnalyticsFeaturesContext>
136 <QueryProvider currentDid={currentAccount?.did}>
137 <PolicyUpdateOverlayProvider>
138 <LiveEventsProvider>
139 <AgeAssuranceV2Provider>
140 <ComposerProvider>
141 <MessagesProvider>
142 {/* LabelDefsProvider MUST come before ModerationOptsProvider */}
143 <LabelDefsProvider>
144 <ModerationOptsProvider>
145 <LoggedOutViewProvider>
146 <SelectedFeedProvider>
147 <HiddenRepliesProvider>
148 <HomeBadgeProvider>
149 <UnreadNotifsProvider>
150 <BackgroundNotificationPreferencesProvider>
151 <MutedThreadsProvider>
152 <SafeAreaProvider>
153 <ProgressGuideProvider>
154 <ServiceConfigProvider>
155 <EmailVerificationProvider>
156 <HideBottomBarBorderProvider>
157 <IntentDialogProvider>
158 <TranslateOnDeviceProvider>
159 <Shell />
160 <ToastOutlet />
161 </TranslateOnDeviceProvider>
162 </IntentDialogProvider>
163 </HideBottomBarBorderProvider>
164 </EmailVerificationProvider>
165 </ServiceConfigProvider>
166 </ProgressGuideProvider>
167 </SafeAreaProvider>
168 </MutedThreadsProvider>
169 </BackgroundNotificationPreferencesProvider>
170 </UnreadNotifsProvider>
171 </HomeBadgeProvider>
172 </HiddenRepliesProvider>
173 </SelectedFeedProvider>
174 </LoggedOutViewProvider>
175 </ModerationOptsProvider>
176 </LabelDefsProvider>
177 </MessagesProvider>
178 </ComposerProvider>
179 </AgeAssuranceV2Provider>
180 </LiveEventsProvider>
181 </PolicyUpdateOverlayProvider>
182 </QueryProvider>
183 </AnalyticsFeaturesContext>
184 </Fragment>
185 </ActiveVideoProvider>
186 </VideoVolumeProvider>
187 </Splash>
188 </ContextMenuProvider>
189 </ThemeProvider>
190 </Alf>
191 )
192}
193
194function App() {
195 const [isReady, setReady] = useState(false)
196
197 useEffect(() => {
198 Promise.all([initPersistedState(), Geo.resolve(), setupDeviceId]).then(() =>
199 setReady(true),
200 )
201 }, [])
202
203 if (!isReady) {
204 return null
205 }
206
207 /*
208 * NOTE: only nothing here can depend on other data or session state, since
209 * that is set up in the InnerApp component above.
210 */
211 return (
212 <Geo.Provider>
213 <AppConfigProvider>
214 <A11yProvider>
215 <KeyboardControllerProvider>
216 <OnboardingProvider>
217 <AnalyticsContext>
218 <SessionProvider>
219 <PrefsStateProvider>
220 <I18nProvider>
221 <ShellStateProvider>
222 <ModalStateProvider>
223 <DialogStateProvider>
224 <LightboxStateProvider>
225 <PortalProvider>
226 <StarterPackProvider>
227 <InnerApp />
228 </StarterPackProvider>
229 </PortalProvider>
230 </LightboxStateProvider>
231 </DialogStateProvider>
232 </ModalStateProvider>
233 </ShellStateProvider>
234 </I18nProvider>
235 </PrefsStateProvider>
236 </SessionProvider>
237 </AnalyticsContext>
238 </OnboardingProvider>
239 </KeyboardControllerProvider>
240 </A11yProvider>
241 </AppConfigProvider>
242 </Geo.Provider>
243 )
244}
245
246export default Sentry.wrap(App)