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