mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import '#/logger/sentry/setup'
2import '#/logger/bitdrift/setup'
3import '#/view/icons'
4
5import React, {useEffect, useState} from 'react'
6import {GestureHandlerRootView} from 'react-native-gesture-handler'
7import {RootSiblingParent} from 'react-native-root-siblings'
8import {
9 initialWindowMetrics,
10 SafeAreaProvider,
11} from 'react-native-safe-area-context'
12import * as ScreenOrientation from 'expo-screen-orientation'
13import * as SplashScreen from 'expo-splash-screen'
14import * as SystemUI from 'expo-system-ui'
15import {msg} from '@lingui/macro'
16import {useLingui} from '@lingui/react'
17import * as Sentry from '@sentry/react-native'
18
19import {KeyboardControllerProvider} from '#/lib/hooks/useEnableKeyboardController'
20import {QueryProvider} from '#/lib/react-query'
21import {Provider as StatsigProvider, tryFetchGates} from '#/lib/statsig/statsig'
22import {s} from '#/lib/styles'
23import {ThemeProvider} from '#/lib/ThemeContext'
24import I18nProvider from '#/locale/i18nProvider'
25import {logger} from '#/logger'
26import {isAndroid, isIOS} from '#/platform/detection'
27import {Provider as A11yProvider} from '#/state/a11y'
28import {Provider as MutedThreadsProvider} from '#/state/cache/thread-mutes'
29import {Provider as DialogStateProvider} from '#/state/dialogs'
30import {listenSessionDropped} from '#/state/events'
31import {
32 beginResolveGeolocation,
33 ensureGeolocationResolved,
34 Provider as GeolocationProvider,
35} from '#/state/geolocation'
36import {Provider as HomeBadgeProvider} from '#/state/home-badge'
37import {Provider as InvitesStateProvider} from '#/state/invites'
38import {Provider as LightboxStateProvider} from '#/state/lightbox'
39import {MessagesProvider} from '#/state/messages'
40import {Provider as ModalStateProvider} from '#/state/modals'
41import {init as initPersistedState} from '#/state/persisted'
42import {Provider as PrefsStateProvider} from '#/state/preferences'
43import {Provider as LabelDefsProvider} from '#/state/preferences/label-defs'
44import {Provider as ModerationOptsProvider} from '#/state/preferences/moderation-opts'
45import {Provider as UnreadNotifsProvider} from '#/state/queries/notifications/unread'
46import {Provider as ServiceAccountManager} from '#/state/service-config'
47import {
48 Provider as SessionProvider,
49 type SessionAccount,
50 useSession,
51 useSessionApi,
52} from '#/state/session'
53import {readLastActiveAccount} from '#/state/session/util'
54import {Provider as ShellStateProvider} from '#/state/shell'
55import {Provider as ComposerProvider} from '#/state/shell/composer'
56import {Provider as LoggedOutViewProvider} from '#/state/shell/logged-out'
57import {Provider as ProgressGuideProvider} from '#/state/shell/progress-guide'
58import {Provider as SelectedFeedProvider} from '#/state/shell/selected-feed'
59import {Provider as StarterPackProvider} from '#/state/shell/starter-pack'
60import {Provider as HiddenRepliesProvider} from '#/state/threadgate-hidden-replies'
61import {TestCtrls} from '#/view/com/testing/TestCtrls'
62import * as Toast from '#/view/com/util/Toast'
63import {Shell} from '#/view/shell'
64import {ThemeProvider as Alf} from '#/alf'
65import {useColorModeTheme} from '#/alf/util/useColorModeTheme'
66import {Provider as ContextMenuProvider} from '#/components/ContextMenu'
67import {NuxDialogs} from '#/components/dialogs/nuxs'
68import {useStarterPackEntry} from '#/components/hooks/useStarterPackEntry'
69import {Provider as IntentDialogProvider} from '#/components/intents/IntentDialogs'
70import {Provider as PortalProvider} from '#/components/Portal'
71import {Provider as VideoVolumeProvider} from '#/components/Post/Embed/VideoEmbed/VideoVolumeContext'
72import {Splash} from '#/Splash'
73import {BottomSheetProvider} from '../modules/bottom-sheet'
74import {BackgroundNotificationPreferencesProvider} from '../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider'
75import {Provider as HideBottomBarBorderProvider} from './lib/hooks/useHideBottomBarBorder'
76
77SplashScreen.preventAutoHideAsync()
78if (isIOS) {
79 SystemUI.setBackgroundColorAsync('black')
80}
81if (isAndroid) {
82 // iOS is handled by the config plugin -sfn
83 ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT_UP)
84}
85
86/**
87 * Begin geolocation ASAP
88 */
89beginResolveGeolocation()
90
91function InnerApp() {
92 const [isReady, setIsReady] = React.useState(false)
93 const {currentAccount} = useSession()
94 const {resumeSession} = useSessionApi()
95 const theme = useColorModeTheme()
96 const {_} = useLingui()
97
98 const hasCheckedReferrer = useStarterPackEntry()
99
100 // init
101 useEffect(() => {
102 async function onLaunch(account?: SessionAccount) {
103 try {
104 if (account) {
105 await resumeSession(account)
106 } else {
107 await tryFetchGates(undefined, 'prefer-fresh-gates')
108 }
109 } catch (e) {
110 logger.error(`session: resume failed`, {message: e})
111 } finally {
112 setIsReady(true)
113 }
114 }
115 const account = readLastActiveAccount()
116 onLaunch(account)
117 }, [resumeSession])
118
119 useEffect(() => {
120 return listenSessionDropped(() => {
121 Toast.show(
122 _(msg`Sorry! Your session expired. Please sign in again.`),
123 'info',
124 )
125 })
126 }, [_])
127
128 return (
129 <Alf theme={theme}>
130 <ThemeProvider theme={theme}>
131 <ContextMenuProvider>
132 <Splash isReady={isReady && hasCheckedReferrer}>
133 <RootSiblingParent>
134 <VideoVolumeProvider>
135 <React.Fragment
136 // Resets the entire tree below when it changes:
137 key={currentAccount?.did}>
138 <QueryProvider currentDid={currentAccount?.did}>
139 <ComposerProvider>
140 <StatsigProvider>
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 <ProgressGuideProvider>
153 <ServiceAccountManager>
154 <HideBottomBarBorderProvider>
155 <GestureHandlerRootView
156 style={s.h100pct}>
157 <IntentDialogProvider>
158 <TestCtrls />
159 <Shell />
160 <NuxDialogs />
161 </IntentDialogProvider>
162 </GestureHandlerRootView>
163 </HideBottomBarBorderProvider>
164 </ServiceAccountManager>
165 </ProgressGuideProvider>
166 </MutedThreadsProvider>
167 </BackgroundNotificationPreferencesProvider>
168 </UnreadNotifsProvider>
169 </HomeBadgeProvider>
170 </HiddenRepliesProvider>
171 </SelectedFeedProvider>
172 </LoggedOutViewProvider>
173 </ModerationOptsProvider>
174 </LabelDefsProvider>
175 </MessagesProvider>
176 </StatsigProvider>
177 </ComposerProvider>
178 </QueryProvider>
179 </React.Fragment>
180 </VideoVolumeProvider>
181 </RootSiblingParent>
182 </Splash>
183 </ContextMenuProvider>
184 </ThemeProvider>
185 </Alf>
186 )
187}
188
189function App() {
190 const [isReady, setReady] = useState(false)
191
192 React.useEffect(() => {
193 Promise.all([initPersistedState(), ensureGeolocationResolved()]).then(() =>
194 setReady(true),
195 )
196 }, [])
197
198 if (!isReady) {
199 return null
200 }
201
202 /*
203 * NOTE: only nothing here can depend on other data or session state, since
204 * that is set up in the InnerApp component above.
205 */
206 return (
207 <GeolocationProvider>
208 <A11yProvider>
209 <KeyboardControllerProvider>
210 <SessionProvider>
211 <PrefsStateProvider>
212 <I18nProvider>
213 <ShellStateProvider>
214 <InvitesStateProvider>
215 <ModalStateProvider>
216 <DialogStateProvider>
217 <LightboxStateProvider>
218 <PortalProvider>
219 <BottomSheetProvider>
220 <StarterPackProvider>
221 <SafeAreaProvider
222 initialMetrics={initialWindowMetrics}>
223 <InnerApp />
224 </SafeAreaProvider>
225 </StarterPackProvider>
226 </BottomSheetProvider>
227 </PortalProvider>
228 </LightboxStateProvider>
229 </DialogStateProvider>
230 </ModalStateProvider>
231 </InvitesStateProvider>
232 </ShellStateProvider>
233 </I18nProvider>
234 </PrefsStateProvider>
235 </SessionProvider>
236 </KeyboardControllerProvider>
237 </A11yProvider>
238 </GeolocationProvider>
239 )
240}
241
242export default Sentry.wrap(App)