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