61004b887b
* WIP * Sorting working * Rough handling of hidden/muted * Better muted/hidden sorting and handling * Clarify some naming * Fix parents * Handle first reply under highlighted/composer * WIP RaW * WIP optimistic * Optimistic WIP * Little cleanup, inserting dupes * Re-org * Add in new optimistic insert logic * Update types * Sorta working linear view optimistic state * Simple working version, no pref for OP * Working optimistic reply insertions, preference for OP * Ensure deletes are coming through * WIP scroll handling * WIP scroll tweaks * Clean up scrolling * Clean up onPostSuccess * Add annotations * Fix highlighted post calc * WIP kill me * Update APIs * Nvm don't kill me * Fix optimistic insert * Handle read more cases in tree view * Basically working read more * Handle linear view * Reorg * More reorg * Split up thread post components * New reply tree layout * Fix up traversal metadata * Tighten some spacing * Use indent ya idiot * Some linear mode cleanup * Fix lines on read more items * Vibe coding to success * Almost there with read mores * Update APIs * Bump sdk * Update import * Checkpoint new traversal * Checkpoint cleanup * Checkpoint, need to fix blocked posts * Checkpoint: think we're good, needs more cleanup * Clean it up * Two passes only * Set to default params, update comment * Fix render bug on native * Checkpoint parent rendering, can opt for slower handling here * Clean up parent handling, reply handling * Fix read more extra space * Fix read more in linear view * Fix hidden reply handling, seen count, before/after calc * Update naming * Rename Slice to ThreadItem * Add basic post and anchor skeletons * Refactor client-side hidden * WIP hidden fetching * Update types * Clean up query a bit * Scrolling still broken * Ok maybe fix scrolling * Checkpoint move state into meta query * Don't load remote hidden items unless needed * skeleton view * Reset hidden items when params change * Split up traversal and avoid multiple passes * Clean up * Checkpoint: handling exhausted replies * Clean up traversal functions further * Clean up pagination * Limit optimistic reply depth * Handle optimistic insert in hidden replies * Share root query key for easier cache extraction * Make blurred posts not look like ass * Fix double deleted item * Make optimistic deleted state not look like crap in tree view * Fix parents traversal 4 real * Rename tree post * Make optimistic deletions of linear posts not look bad * Rename linear post components * Handle tombstone views * Rename read more component * Add moreParents handling * Align interaction states of read more * Fix read more on FF * Tree view skeleton * Reply composer skele * Remove hack for showing more replies * Checkpoint: sort change scrolling fixed * Checkpoint: learned new things, reset to base * Feature gate * Rename * Replace show more * Update settings screen * Update pkg and endpoint * Remove console * Eureka * Cleanup last commit * No tests atm * Remove scroll provider * Clean up callbacks, better error state * Remove todo * Remove todo * Remove todos * Format * Ok I think scrolling is solid * Add back mobile compose input * Ok need to compute headerHeight every time * Update comments * Ok button up web too * Threads v2 tweaks (#8467) * fix error screen collapsing * use personx icon for blocked posts * Remove height/width * Revert unused Header change * Clarify code * Relate consts to theme values * Remove debug code * Typo * Fix debounce of threads prefs * Update metadata comments, dev mode * Missed a spot * Clean up todo * Fix up no-unauthenticated posts * Truncate parents if no-unauth * Update getBranch docs * Remove debug code * Expand fetching in some cases * Clear scroll need for root post to fix jump bug * Fix reply composer skeleton state * Remove uneeded initialized value * Add profile shadow cache * Some metrics * prettier tweak * eslint ignore * Fix optimistic insertion * Typo * Rename, comment * Remove wait * Counter naming * Replies seen counter for moderated sub-trees * Remove borders on skeleton * Align tombstone with optimistic deletion state * Fix optimistic deletion for thread * Add tree view icon * Rename * Cleanup * Update settings copy * Header menu open metric * Bump package * Better reply prompt (#8474) * restyle reply prompt * hide bottom bar border for cleaner look * use new border hiding hook in DMs * create `transparentifyColor` function * adjust padding * fix padding in immersive lpayer * Apply suggestions from code review Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> * Integrate post-source (cherry picked from commit fe053e9b38395a4fcb30a4367bc800f64ea84fe9) --------- Co-authored-by: Samuel Newman <mozzius@protonmail.com> Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>
243 lines
9.7 KiB
TypeScript
243 lines
9.7 KiB
TypeScript
import '#/logger/sentry/setup'
|
|
import '#/logger/bitdrift/setup'
|
|
import '#/view/icons'
|
|
|
|
import React, {useEffect, useState} from 'react'
|
|
import {GestureHandlerRootView} from 'react-native-gesture-handler'
|
|
import {RootSiblingParent} from 'react-native-root-siblings'
|
|
import {
|
|
initialWindowMetrics,
|
|
SafeAreaProvider,
|
|
} from 'react-native-safe-area-context'
|
|
import * as ScreenOrientation from 'expo-screen-orientation'
|
|
import * as SplashScreen from 'expo-splash-screen'
|
|
import * as SystemUI from 'expo-system-ui'
|
|
import {msg} from '@lingui/macro'
|
|
import {useLingui} from '@lingui/react'
|
|
import * as Sentry from '@sentry/react-native'
|
|
|
|
import {KeyboardControllerProvider} from '#/lib/hooks/useEnableKeyboardController'
|
|
import {QueryProvider} from '#/lib/react-query'
|
|
import {Provider as StatsigProvider, tryFetchGates} from '#/lib/statsig/statsig'
|
|
import {s} from '#/lib/styles'
|
|
import {ThemeProvider} from '#/lib/ThemeContext'
|
|
import I18nProvider from '#/locale/i18nProvider'
|
|
import {logger} from '#/logger'
|
|
import {isAndroid, isIOS} from '#/platform/detection'
|
|
import {Provider as A11yProvider} from '#/state/a11y'
|
|
import {Provider as MutedThreadsProvider} from '#/state/cache/thread-mutes'
|
|
import {Provider as DialogStateProvider} from '#/state/dialogs'
|
|
import {listenSessionDropped} from '#/state/events'
|
|
import {
|
|
beginResolveGeolocation,
|
|
ensureGeolocationResolved,
|
|
Provider as GeolocationProvider,
|
|
} from '#/state/geolocation'
|
|
import {Provider as HomeBadgeProvider} from '#/state/home-badge'
|
|
import {Provider as InvitesStateProvider} from '#/state/invites'
|
|
import {Provider as LightboxStateProvider} from '#/state/lightbox'
|
|
import {MessagesProvider} from '#/state/messages'
|
|
import {Provider as ModalStateProvider} from '#/state/modals'
|
|
import {init as initPersistedState} from '#/state/persisted'
|
|
import {Provider as PrefsStateProvider} from '#/state/preferences'
|
|
import {Provider as LabelDefsProvider} from '#/state/preferences/label-defs'
|
|
import {Provider as ModerationOptsProvider} from '#/state/preferences/moderation-opts'
|
|
import {Provider as UnreadNotifsProvider} from '#/state/queries/notifications/unread'
|
|
import {Provider as ServiceAccountManager} from '#/state/service-config'
|
|
import {
|
|
Provider as SessionProvider,
|
|
type SessionAccount,
|
|
useSession,
|
|
useSessionApi,
|
|
} from '#/state/session'
|
|
import {readLastActiveAccount} from '#/state/session/util'
|
|
import {Provider as ShellStateProvider} from '#/state/shell'
|
|
import {Provider as ComposerProvider} from '#/state/shell/composer'
|
|
import {Provider as LoggedOutViewProvider} from '#/state/shell/logged-out'
|
|
import {Provider as ProgressGuideProvider} from '#/state/shell/progress-guide'
|
|
import {Provider as SelectedFeedProvider} from '#/state/shell/selected-feed'
|
|
import {Provider as StarterPackProvider} from '#/state/shell/starter-pack'
|
|
import {Provider as HiddenRepliesProvider} from '#/state/threadgate-hidden-replies'
|
|
import {TestCtrls} from '#/view/com/testing/TestCtrls'
|
|
import {Provider as VideoVolumeProvider} from '#/view/com/util/post-embeds/VideoVolumeContext'
|
|
import * as Toast from '#/view/com/util/Toast'
|
|
import {Shell} from '#/view/shell'
|
|
import {ThemeProvider as Alf} from '#/alf'
|
|
import {useColorModeTheme} from '#/alf/util/useColorModeTheme'
|
|
import {Provider as ContextMenuProvider} from '#/components/ContextMenu'
|
|
import {NuxDialogs} from '#/components/dialogs/nuxs'
|
|
import {useStarterPackEntry} from '#/components/hooks/useStarterPackEntry'
|
|
import {Provider as IntentDialogProvider} from '#/components/intents/IntentDialogs'
|
|
import {Provider as PortalProvider} from '#/components/Portal'
|
|
import {Splash} from '#/Splash'
|
|
import {BottomSheetProvider} from '../modules/bottom-sheet'
|
|
import {BackgroundNotificationPreferencesProvider} from '../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider'
|
|
import {Provider as HideBottomBarBorderProvider} from './lib/hooks/useHideBottomBarBorder'
|
|
|
|
SplashScreen.preventAutoHideAsync()
|
|
if (isIOS) {
|
|
SystemUI.setBackgroundColorAsync('black')
|
|
}
|
|
if (isAndroid) {
|
|
// iOS is handled by the config plugin -sfn
|
|
ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT_UP)
|
|
}
|
|
|
|
/**
|
|
* Begin geolocation ASAP
|
|
*/
|
|
beginResolveGeolocation()
|
|
|
|
function InnerApp() {
|
|
const [isReady, setIsReady] = React.useState(false)
|
|
const {currentAccount} = useSession()
|
|
const {resumeSession} = useSessionApi()
|
|
const theme = useColorModeTheme()
|
|
const {_} = useLingui()
|
|
|
|
const hasCheckedReferrer = useStarterPackEntry()
|
|
|
|
// init
|
|
useEffect(() => {
|
|
async function onLaunch(account?: SessionAccount) {
|
|
try {
|
|
if (account) {
|
|
await resumeSession(account)
|
|
} else {
|
|
await tryFetchGates(undefined, 'prefer-fresh-gates')
|
|
}
|
|
} catch (e) {
|
|
logger.error(`session: resume failed`, {message: e})
|
|
} finally {
|
|
setIsReady(true)
|
|
}
|
|
}
|
|
const account = readLastActiveAccount()
|
|
onLaunch(account)
|
|
}, [resumeSession])
|
|
|
|
useEffect(() => {
|
|
return listenSessionDropped(() => {
|
|
Toast.show(
|
|
_(msg`Sorry! Your session expired. Please sign in again.`),
|
|
'info',
|
|
)
|
|
})
|
|
}, [_])
|
|
|
|
return (
|
|
<Alf theme={theme}>
|
|
<ThemeProvider theme={theme}>
|
|
<ContextMenuProvider>
|
|
<Splash isReady={isReady && hasCheckedReferrer}>
|
|
<RootSiblingParent>
|
|
<VideoVolumeProvider>
|
|
<React.Fragment
|
|
// Resets the entire tree below when it changes:
|
|
key={currentAccount?.did}>
|
|
<QueryProvider currentDid={currentAccount?.did}>
|
|
<ComposerProvider>
|
|
<StatsigProvider>
|
|
<MessagesProvider>
|
|
{/* LabelDefsProvider MUST come before ModerationOptsProvider */}
|
|
<LabelDefsProvider>
|
|
<ModerationOptsProvider>
|
|
<LoggedOutViewProvider>
|
|
<SelectedFeedProvider>
|
|
<HiddenRepliesProvider>
|
|
<HomeBadgeProvider>
|
|
<UnreadNotifsProvider>
|
|
<BackgroundNotificationPreferencesProvider>
|
|
<MutedThreadsProvider>
|
|
<ProgressGuideProvider>
|
|
<ServiceAccountManager>
|
|
<HideBottomBarBorderProvider>
|
|
<GestureHandlerRootView
|
|
style={s.h100pct}>
|
|
<IntentDialogProvider>
|
|
<TestCtrls />
|
|
<Shell />
|
|
<NuxDialogs />
|
|
</IntentDialogProvider>
|
|
</GestureHandlerRootView>
|
|
</HideBottomBarBorderProvider>
|
|
</ServiceAccountManager>
|
|
</ProgressGuideProvider>
|
|
</MutedThreadsProvider>
|
|
</BackgroundNotificationPreferencesProvider>
|
|
</UnreadNotifsProvider>
|
|
</HomeBadgeProvider>
|
|
</HiddenRepliesProvider>
|
|
</SelectedFeedProvider>
|
|
</LoggedOutViewProvider>
|
|
</ModerationOptsProvider>
|
|
</LabelDefsProvider>
|
|
</MessagesProvider>
|
|
</StatsigProvider>
|
|
</ComposerProvider>
|
|
</QueryProvider>
|
|
</React.Fragment>
|
|
</VideoVolumeProvider>
|
|
</RootSiblingParent>
|
|
</Splash>
|
|
</ContextMenuProvider>
|
|
</ThemeProvider>
|
|
</Alf>
|
|
)
|
|
}
|
|
|
|
function App() {
|
|
const [isReady, setReady] = useState(false)
|
|
|
|
React.useEffect(() => {
|
|
Promise.all([initPersistedState(), ensureGeolocationResolved()]).then(() =>
|
|
setReady(true),
|
|
)
|
|
}, [])
|
|
|
|
if (!isReady) {
|
|
return null
|
|
}
|
|
|
|
/*
|
|
* NOTE: only nothing here can depend on other data or session state, since
|
|
* that is set up in the InnerApp component above.
|
|
*/
|
|
return (
|
|
<GeolocationProvider>
|
|
<A11yProvider>
|
|
<KeyboardControllerProvider>
|
|
<SessionProvider>
|
|
<PrefsStateProvider>
|
|
<I18nProvider>
|
|
<ShellStateProvider>
|
|
<InvitesStateProvider>
|
|
<ModalStateProvider>
|
|
<DialogStateProvider>
|
|
<LightboxStateProvider>
|
|
<PortalProvider>
|
|
<BottomSheetProvider>
|
|
<StarterPackProvider>
|
|
<SafeAreaProvider
|
|
initialMetrics={initialWindowMetrics}>
|
|
<InnerApp />
|
|
</SafeAreaProvider>
|
|
</StarterPackProvider>
|
|
</BottomSheetProvider>
|
|
</PortalProvider>
|
|
</LightboxStateProvider>
|
|
</DialogStateProvider>
|
|
</ModalStateProvider>
|
|
</InvitesStateProvider>
|
|
</ShellStateProvider>
|
|
</I18nProvider>
|
|
</PrefsStateProvider>
|
|
</SessionProvider>
|
|
</KeyboardControllerProvider>
|
|
</A11yProvider>
|
|
</GeolocationProvider>
|
|
)
|
|
}
|
|
|
|
export default Sentry.wrap(App)
|