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 {Provider as StatsigProvider} from '#/lib/statsig/statsig'
18import {logger} from '#/logger'
19import {MessagesProvider} from '#/state/messages'
20import {init as initPersistedState} from '#/state/persisted'
21import {Provider as LabelDefsProvider} from '#/state/preferences/label-defs'
22import {Provider as ModerationOptsProvider} from '#/state/preferences/moderation-opts'
23import {readLastActiveAccount} from '#/state/session/util'
24import {useIntentHandler} from 'lib/hooks/useIntentHandler'
25import {QueryProvider} from 'lib/react-query'
26import {s} from 'lib/styles'
27import {ThemeProvider} from 'lib/ThemeContext'
28import {Provider as DialogStateProvider} from 'state/dialogs'
29import {Provider as InvitesStateProvider} from 'state/invites'
30import {Provider as LightboxStateProvider} from 'state/lightbox'
31import {Provider as ModalStateProvider} from 'state/modals'
32import {Provider as MutedThreadsProvider} from 'state/muted-threads'
33import {Provider as PrefsStateProvider} from 'state/preferences'
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 {Provider as ShellStateProvider} from 'state/shell'
42import {Provider as LoggedOutViewProvider} from 'state/shell/logged-out'
43import {Provider as SelectedFeedProvider} from 'state/shell/selected-feed'
44import {TestCtrls} from 'view/com/testing/TestCtrls'
45import * as Toast from 'view/com/util/Toast'
46import {Shell} from 'view/shell'
47import {ThemeProvider as Alf} from '#/alf'
48import {useColorModeTheme} from '#/alf/util/useColorModeTheme'
49import {Provider as PortalProvider} from '#/components/Portal'
50import {Splash} from '#/Splash'
51import {BackgroundNotificationPreferencesProvider} from '../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider'
52import I18nProvider from './locale/i18nProvider'
53import {listenSessionDropped} from './state/events'
54
55SplashScreen.preventAutoHideAsync()
56
57function InnerApp() {
58 const [isReady, setIsReady] = React.useState(false)
59 const {currentAccount} = useSession()
60 const {resumeSession} = useSessionApi()
61 const theme = useColorModeTheme()
62 const {_} = useLingui()
63
64 useIntentHandler()
65
66 // init
67 useEffect(() => {
68 async function onLaunch(account?: SessionAccount) {
69 try {
70 if (account) {
71 await resumeSession(account)
72 }
73 } catch (e) {
74 logger.error(`session: resume failed`, {message: e})
75 } finally {
76 setIsReady(true)
77 }
78 }
79 const account = readLastActiveAccount()
80 onLaunch(account)
81 }, [resumeSession])
82
83 useEffect(() => {
84 return listenSessionDropped(() => {
85 Toast.show(_(msg`Sorry! Your session expired. Please log in again.`))
86 })
87 }, [_])
88
89 return (
90 <SafeAreaProvider initialMetrics={initialWindowMetrics}>
91 <Alf theme={theme}>
92 <ThemeProvider theme={theme}>
93 <Splash isReady={isReady}>
94 <RootSiblingParent>
95 <React.Fragment
96 // Resets the entire tree below when it changes:
97 key={currentAccount?.did}>
98 <QueryProvider currentDid={currentAccount?.did}>
99 <StatsigProvider>
100 <MessagesProvider>
101 {/* LabelDefsProvider MUST come before ModerationOptsProvider */}
102 <LabelDefsProvider>
103 <ModerationOptsProvider>
104 <LoggedOutViewProvider>
105 <SelectedFeedProvider>
106 <UnreadNotifsProvider>
107 <BackgroundNotificationPreferencesProvider>
108 <GestureHandlerRootView style={s.h100pct}>
109 <TestCtrls />
110 <Shell />
111 </GestureHandlerRootView>
112 </BackgroundNotificationPreferencesProvider>
113 </UnreadNotifsProvider>
114 </SelectedFeedProvider>
115 </LoggedOutViewProvider>
116 </ModerationOptsProvider>
117 </LabelDefsProvider>
118 </MessagesProvider>
119 </StatsigProvider>
120 </QueryProvider>
121 </React.Fragment>
122 </RootSiblingParent>
123 </Splash>
124 </ThemeProvider>
125 </Alf>
126 </SafeAreaProvider>
127 )
128}
129
130function App() {
131 const [isReady, setReady] = useState(false)
132
133 React.useEffect(() => {
134 initPersistedState().then(() => setReady(true))
135 }, [])
136
137 if (!isReady) {
138 return null
139 }
140
141 /*
142 * NOTE: only nothing here can depend on other data or session state, since
143 * that is set up in the InnerApp component above.
144 */
145 return (
146 <KeyboardProvider enabled={true} statusBarTranslucent={true}>
147 <SessionProvider>
148 <ShellStateProvider>
149 <PrefsStateProvider>
150 <MutedThreadsProvider>
151 <InvitesStateProvider>
152 <ModalStateProvider>
153 <DialogStateProvider>
154 <LightboxStateProvider>
155 <I18nProvider>
156 <PortalProvider>
157 <InnerApp />
158 </PortalProvider>
159 </I18nProvider>
160 </LightboxStateProvider>
161 </DialogStateProvider>
162 </ModalStateProvider>
163 </InvitesStateProvider>
164 </MutedThreadsProvider>
165 </PrefsStateProvider>
166 </ShellStateProvider>
167 </SessionProvider>
168 </KeyboardProvider>
169 )
170}
171
172export default App