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