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