Bluesky app fork with some witchin' additions 馃挮
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

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