PWI: Refactor Shell (#1989)

* Vendor createNativeStackNavigator for further tweaks

* Completely disable withAuthRequired

* Render LoggedOut for protected routes

* Move web shell into the navigator

* Simplify the logic

* Add login modal

* Delete withAuthRequired

* Reset app state on session change

* Move TS suppression
zio/stable
dan 2023-11-24 22:31:33 +00:00 committed by GitHub
parent 4b59a21cac
commit f2d164ec23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 1627 additions and 1665 deletions

View File

@ -28,6 +28,7 @@ import {Provider as LightboxStateProvider} from 'state/lightbox'
import {Provider as MutedThreadsProvider} from 'state/muted-threads' import {Provider as MutedThreadsProvider} from 'state/muted-threads'
import {Provider as InvitesStateProvider} from 'state/invites' import {Provider as InvitesStateProvider} from 'state/invites'
import {Provider as PrefsStateProvider} from 'state/preferences' import {Provider as PrefsStateProvider} from 'state/preferences'
import {Provider as LoggedOutViewProvider} from 'state/shell/logged-out'
import I18nProvider from './locale/i18nProvider' import I18nProvider from './locale/i18nProvider'
import { import {
Provider as SessionProvider, Provider as SessionProvider,
@ -42,7 +43,7 @@ SplashScreen.preventAutoHideAsync()
function InnerApp() { function InnerApp() {
const colorMode = useColorMode() const colorMode = useColorMode()
const {isInitialLoad} = useSession() const {isInitialLoad, currentAccount} = useSession()
const {resumeSession} = useSessionApi() const {resumeSession} = useSessionApi()
// init // init
@ -69,6 +70,10 @@ function InnerApp() {
*/ */
return ( return (
<React.Fragment
// Resets the entire tree below when it changes:
key={currentAccount?.did}>
<LoggedOutViewProvider>
<UnreadNotifsProvider> <UnreadNotifsProvider>
<ThemeProvider theme={colorMode}> <ThemeProvider theme={colorMode}>
<analytics.Provider> <analytics.Provider>
@ -82,6 +87,8 @@ function InnerApp() {
</analytics.Provider> </analytics.Provider>
</ThemeProvider> </ThemeProvider>
</UnreadNotifsProvider> </UnreadNotifsProvider>
</LoggedOutViewProvider>
</React.Fragment>
) )
} }

View File

@ -22,6 +22,7 @@ import {Provider as LightboxStateProvider} from 'state/lightbox'
import {Provider as MutedThreadsProvider} from 'state/muted-threads' import {Provider as MutedThreadsProvider} from 'state/muted-threads'
import {Provider as InvitesStateProvider} from 'state/invites' import {Provider as InvitesStateProvider} from 'state/invites'
import {Provider as PrefsStateProvider} from 'state/preferences' import {Provider as PrefsStateProvider} from 'state/preferences'
import {Provider as LoggedOutViewProvider} from 'state/shell/logged-out'
import I18nProvider from './locale/i18nProvider' import I18nProvider from './locale/i18nProvider'
import { import {
Provider as SessionProvider, Provider as SessionProvider,
@ -34,7 +35,7 @@ import * as persisted from '#/state/persisted'
enableFreeze(true) enableFreeze(true)
function InnerApp() { function InnerApp() {
const {isInitialLoad} = useSession() const {isInitialLoad, currentAccount} = useSession()
const {resumeSession} = useSessionApi() const {resumeSession} = useSessionApi()
const colorMode = useColorMode() const colorMode = useColorMode()
@ -57,6 +58,10 @@ function InnerApp() {
*/ */
return ( return (
<React.Fragment
// Resets the entire tree below when it changes:
key={currentAccount?.did}>
<LoggedOutViewProvider>
<UnreadNotifsProvider> <UnreadNotifsProvider>
<ThemeProvider theme={colorMode}> <ThemeProvider theme={colorMode}>
<analytics.Provider> <analytics.Provider>
@ -70,6 +75,8 @@ function InnerApp() {
</analytics.Provider> </analytics.Provider>
</ThemeProvider> </ThemeProvider>
</UnreadNotifsProvider> </UnreadNotifsProvider>
</LoggedOutViewProvider>
</React.Fragment>
) )
} }

View File

@ -9,7 +9,6 @@ import {
DefaultTheme, DefaultTheme,
DarkTheme, DarkTheme,
} from '@react-navigation/native' } from '@react-navigation/native'
import {createNativeStackNavigator} from '@react-navigation/native-stack'
import { import {
BottomTabBarProps, BottomTabBarProps,
createBottomTabNavigator, createBottomTabNavigator,
@ -69,16 +68,18 @@ import {ModerationBlockedAccounts} from 'view/screens/ModerationBlockedAccounts'
import {SavedFeeds} from 'view/screens/SavedFeeds' import {SavedFeeds} from 'view/screens/SavedFeeds'
import {PreferencesHomeFeed} from 'view/screens/PreferencesHomeFeed' import {PreferencesHomeFeed} from 'view/screens/PreferencesHomeFeed'
import {PreferencesThreads} from 'view/screens/PreferencesThreads' import {PreferencesThreads} from 'view/screens/PreferencesThreads'
import {createNativeStackNavigatorWithAuth} from './view/shell/createNativeStackNavigatorWithAuth'
const navigationRef = createNavigationContainerRef<AllNavigatorParams>() const navigationRef = createNavigationContainerRef<AllNavigatorParams>()
const HomeTab = createNativeStackNavigator<HomeTabNavigatorParams>() const HomeTab = createNativeStackNavigatorWithAuth<HomeTabNavigatorParams>()
const SearchTab = createNativeStackNavigator<SearchTabNavigatorParams>() const SearchTab = createNativeStackNavigatorWithAuth<SearchTabNavigatorParams>()
const FeedsTab = createNativeStackNavigator<FeedsTabNavigatorParams>() const FeedsTab = createNativeStackNavigatorWithAuth<FeedsTabNavigatorParams>()
const NotificationsTab = const NotificationsTab =
createNativeStackNavigator<NotificationsTabNavigatorParams>() createNativeStackNavigatorWithAuth<NotificationsTabNavigatorParams>()
const MyProfileTab = createNativeStackNavigator<MyProfileTabNavigatorParams>() const MyProfileTab =
const Flat = createNativeStackNavigator<FlatNavigatorParams>() createNativeStackNavigatorWithAuth<MyProfileTabNavigatorParams>()
const Flat = createNativeStackNavigatorWithAuth<FlatNavigatorParams>()
const Tab = createBottomTabNavigator<BottomTabNavigatorParams>() const Tab = createBottomTabNavigator<BottomTabNavigatorParams>()
/** /**
@ -97,37 +98,37 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
<Stack.Screen <Stack.Screen
name="Lists" name="Lists"
component={ListsScreen} component={ListsScreen}
options={{title: title('Lists')}} options={{title: title('Lists'), requireAuth: true}}
/> />
<Stack.Screen <Stack.Screen
name="Moderation" name="Moderation"
getComponent={() => ModerationScreen} getComponent={() => ModerationScreen}
options={{title: title('Moderation')}} options={{title: title('Moderation'), requireAuth: true}}
/> />
<Stack.Screen <Stack.Screen
name="ModerationModlists" name="ModerationModlists"
getComponent={() => ModerationModlistsScreen} getComponent={() => ModerationModlistsScreen}
options={{title: title('Moderation Lists')}} options={{title: title('Moderation Lists'), requireAuth: true}}
/> />
<Stack.Screen <Stack.Screen
name="ModerationMutedAccounts" name="ModerationMutedAccounts"
getComponent={() => ModerationMutedAccounts} getComponent={() => ModerationMutedAccounts}
options={{title: title('Muted Accounts')}} options={{title: title('Muted Accounts'), requireAuth: true}}
/> />
<Stack.Screen <Stack.Screen
name="ModerationBlockedAccounts" name="ModerationBlockedAccounts"
getComponent={() => ModerationBlockedAccounts} getComponent={() => ModerationBlockedAccounts}
options={{title: title('Blocked Accounts')}} options={{title: title('Blocked Accounts'), requireAuth: true}}
/> />
<Stack.Screen <Stack.Screen
name="Settings" name="Settings"
getComponent={() => SettingsScreen} getComponent={() => SettingsScreen}
options={{title: title('Settings')}} options={{title: title('Settings'), requireAuth: true}}
/> />
<Stack.Screen <Stack.Screen
name="LanguageSettings" name="LanguageSettings"
getComponent={() => LanguageSettingsScreen} getComponent={() => LanguageSettingsScreen}
options={{title: title('Language Settings')}} options={{title: title('Language Settings'), requireAuth: true}}
/> />
<Stack.Screen <Stack.Screen
name="Profile" name="Profile"
@ -154,7 +155,7 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
<Stack.Screen <Stack.Screen
name="ProfileList" name="ProfileList"
getComponent={() => ProfileListScreen} getComponent={() => ProfileListScreen}
options={{title: title('List')}} options={{title: title('List'), requireAuth: true}}
/> />
<Stack.Screen <Stack.Screen
name="PostThread" name="PostThread"
@ -184,12 +185,12 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
<Stack.Screen <Stack.Screen
name="Debug" name="Debug"
getComponent={() => DebugScreen} getComponent={() => DebugScreen}
options={{title: title('Debug')}} options={{title: title('Debug'), requireAuth: true}}
/> />
<Stack.Screen <Stack.Screen
name="Log" name="Log"
getComponent={() => LogScreen} getComponent={() => LogScreen}
options={{title: title('Log')}} options={{title: title('Log'), requireAuth: true}}
/> />
<Stack.Screen <Stack.Screen
name="Support" name="Support"
@ -219,22 +220,22 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
<Stack.Screen <Stack.Screen
name="AppPasswords" name="AppPasswords"
getComponent={() => AppPasswords} getComponent={() => AppPasswords}
options={{title: title('App Passwords')}} options={{title: title('App Passwords'), requireAuth: true}}
/> />
<Stack.Screen <Stack.Screen
name="SavedFeeds" name="SavedFeeds"
getComponent={() => SavedFeeds} getComponent={() => SavedFeeds}
options={{title: title('Edit My Feeds')}} options={{title: title('Edit My Feeds'), requireAuth: true}}
/> />
<Stack.Screen <Stack.Screen
name="PreferencesHomeFeed" name="PreferencesHomeFeed"
getComponent={() => PreferencesHomeFeed} getComponent={() => PreferencesHomeFeed}
options={{title: title('Home Feed Preferences')}} options={{title: title('Home Feed Preferences'), requireAuth: true}}
/> />
<Stack.Screen <Stack.Screen
name="PreferencesThreads" name="PreferencesThreads"
getComponent={() => PreferencesThreads} getComponent={() => PreferencesThreads}
options={{title: title('Threads Preferences')}} options={{title: title('Threads Preferences'), requireAuth: true}}
/> />
</> </>
) )
@ -339,6 +340,7 @@ function NotificationsTabNavigator() {
<NotificationsTab.Screen <NotificationsTab.Screen
name="Notifications" name="Notifications"
getComponent={() => NotificationsScreen} getComponent={() => NotificationsScreen}
options={{requireAuth: true}}
/> />
{commonScreens(NotificationsTab as typeof HomeTab)} {commonScreens(NotificationsTab as typeof HomeTab)}
</NotificationsTab.Navigator> </NotificationsTab.Navigator>
@ -357,8 +359,8 @@ function MyProfileTabNavigator() {
contentStyle, contentStyle,
}}> }}>
<MyProfileTab.Screen <MyProfileTab.Screen
name="MyProfile"
// @ts-ignore // TODO: fix this broken type in ProfileScreen // @ts-ignore // TODO: fix this broken type in ProfileScreen
name="MyProfile"
getComponent={() => ProfileScreen} getComponent={() => ProfileScreen}
initialParams={{ initialParams={{
name: 'me', name: 'me',
@ -405,7 +407,7 @@ const FlatNavigator = () => {
<Flat.Screen <Flat.Screen
name="Notifications" name="Notifications"
getComponent={() => NotificationsScreen} getComponent={() => NotificationsScreen}
options={{title: title('Notifications')}} options={{title: title('Notifications'), requireAuth: true}}
/> />
{commonScreens(Flat as typeof HomeTab, numUnread)} {commonScreens(Flat as typeof HomeTab, numUnread)}
</Flat.Navigator> </Flat.Navigator>

View File

@ -7,7 +7,6 @@ import {Provider as ColorModeProvider} from './color-mode'
import {Provider as OnboardingProvider} from './onboarding' import {Provider as OnboardingProvider} from './onboarding'
import {Provider as ComposerProvider} from './composer' import {Provider as ComposerProvider} from './composer'
import {Provider as TickEveryMinuteProvider} from './tick-every-minute' import {Provider as TickEveryMinuteProvider} from './tick-every-minute'
import {Provider as LoggedOutViewProvider} from './logged-out'
export {useIsDrawerOpen, useSetDrawerOpen} from './drawer-open' export {useIsDrawerOpen, useSetDrawerOpen} from './drawer-open'
export { export {
@ -23,23 +22,19 @@ export {useTickEveryMinute} from './tick-every-minute'
export function Provider({children}: React.PropsWithChildren<{}>) { export function Provider({children}: React.PropsWithChildren<{}>) {
return ( return (
<ShellLayoutProvder> <ShellLayoutProvder>
<LoggedOutViewProvider>
<DrawerOpenProvider> <DrawerOpenProvider>
<DrawerSwipableProvider> <DrawerSwipableProvider>
<MinimalModeProvider> <MinimalModeProvider>
<ColorModeProvider> <ColorModeProvider>
<OnboardingProvider> <OnboardingProvider>
<ComposerProvider> <ComposerProvider>
<TickEveryMinuteProvider> <TickEveryMinuteProvider>{children}</TickEveryMinuteProvider>
{children}
</TickEveryMinuteProvider>
</ComposerProvider> </ComposerProvider>
</OnboardingProvider> </OnboardingProvider>
</ColorModeProvider> </ColorModeProvider>
</MinimalModeProvider> </MinimalModeProvider>
</DrawerSwipableProvider> </DrawerSwipableProvider>
</DrawerOpenProvider> </DrawerOpenProvider>
</LoggedOutViewProvider>
</ShellLayoutProvder> </ShellLayoutProvder>
) )
} }

View File

@ -1,94 +0,0 @@
import React from 'react'
import {
ActivityIndicator,
Linking,
StyleSheet,
TouchableOpacity,
} from 'react-native'
import {CenteredView} from '../util/Views'
import {LoggedOut} from './LoggedOut'
import {Onboarding} from './Onboarding'
import {Text} from '../util/text/Text'
import {usePalette} from 'lib/hooks/usePalette'
import {STATUS_PAGE_URL} from 'lib/constants'
import {useOnboardingState} from '#/state/shell'
import {useSession} from '#/state/session'
import {
useLoggedOutView,
useLoggedOutViewControls,
} from '#/state/shell/logged-out'
import {IS_PROD} from '#/env'
export const withAuthRequired = <P extends object>(
Component: React.ComponentType<P>,
options: {
isPublic?: boolean // TODO(pwi) need to enable in TF somehow
} = {},
): React.FC<P> =>
function AuthRequired(props: P) {
const {isInitialLoad, hasSession} = useSession()
const onboardingState = useOnboardingState()
const {showLoggedOut} = useLoggedOutView()
const {setShowLoggedOut} = useLoggedOutViewControls()
if (isInitialLoad) {
return <Loading />
}
if (!hasSession) {
if (showLoggedOut) {
return <LoggedOut onDismiss={() => setShowLoggedOut(false)} />
} else if (!options?.isPublic || IS_PROD) {
return <LoggedOut />
}
}
if (onboardingState.isActive) {
return <Onboarding />
}
return <Component {...props} />
}
function Loading() {
const pal = usePalette('default')
const [isTakingTooLong, setIsTakingTooLong] = React.useState(false)
React.useEffect(() => {
const t = setTimeout(() => setIsTakingTooLong(true), 15e3) // 15 seconds
return () => clearTimeout(t)
}, [setIsTakingTooLong])
return (
<CenteredView style={[styles.loading, pal.view]}>
<ActivityIndicator size="large" />
<Text type="2xl" style={[styles.loadingText, pal.textLight]}>
{isTakingTooLong
? "This is taking too long. There may be a problem with your internet or with the service, but we're going to try a couple more times..."
: 'Connecting...'}
</Text>
{isTakingTooLong ? (
<TouchableOpacity
onPress={() => {
Linking.openURL(STATUS_PAGE_URL)
}}
accessibilityRole="button">
<Text type="2xl" style={[styles.loadingText, pal.link]}>
Check Bluesky status page
</Text>
</TouchableOpacity>
) : null}
</CenteredView>
)
}
const styles = StyleSheet.create({
loading: {
height: '100%',
alignContent: 'center',
justifyContent: 'center',
paddingBottom: 100,
},
loadingText: {
paddingVertical: 20,
paddingHorizontal: 20,
textAlign: 'center',
},
})

View File

@ -12,7 +12,6 @@ import {Button} from '../com/util/forms/Button'
import * as Toast from '../com/util/Toast' import * as Toast from '../com/util/Toast'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {NativeStackScreenProps} from '@react-navigation/native-stack' import {NativeStackScreenProps} from '@react-navigation/native-stack'
import {CommonNavigatorParams} from 'lib/routes/types' import {CommonNavigatorParams} from 'lib/routes/types'
import {useAnalytics} from 'lib/analytics/analytics' import {useAnalytics} from 'lib/analytics/analytics'
@ -32,8 +31,7 @@ import {ErrorScreen} from '../com/util/error/ErrorScreen'
import {cleanError} from '#/lib/strings/errors' import {cleanError} from '#/lib/strings/errors'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'AppPasswords'> type Props = NativeStackScreenProps<CommonNavigatorParams, 'AppPasswords'>
export const AppPasswords = withAuthRequired( export function AppPasswords({}: Props) {
function AppPasswordsImpl({}: Props) {
const pal = usePalette('default') const pal = usePalette('default')
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
const {screen} = useAnalytics() const {screen} = useAnalytics()
@ -86,8 +84,8 @@ export const AppPasswords = withAuthRequired(
<View style={[styles.empty, pal.viewLight]}> <View style={[styles.empty, pal.viewLight]}>
<Text type="lg" style={[pal.text, styles.emptyText]}> <Text type="lg" style={[pal.text, styles.emptyText]}>
<Trans> <Trans>
You have not created any app passwords yet. You can create one You have not created any app passwords yet. You can create one by
by pressing the button below. pressing the button below.
</Trans> </Trans>
</Text> </Text>
</View> </View>
@ -177,8 +175,7 @@ export const AppPasswords = withAuthRequired(
<ActivityIndicator /> <ActivityIndicator />
</CenteredView> </CenteredView>
) )
}, }
)
function AppPasswordsHeader() { function AppPasswordsHeader() {
const {isTabletOrDesktop} = useWebMediaQueries() const {isTabletOrDesktop} = useWebMediaQueries()

View File

@ -2,7 +2,6 @@ import React from 'react'
import {ActivityIndicator, StyleSheet, View, RefreshControl} from 'react-native' import {ActivityIndicator, StyleSheet, View, RefreshControl} from 'react-native'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {ViewHeader} from 'view/com/util/ViewHeader' import {ViewHeader} from 'view/com/util/ViewHeader'
import {FAB} from 'view/com/util/fab/FAB' import {FAB} from 'view/com/util/fab/FAB'
import {Link} from 'view/com/util/Link' import {Link} from 'view/com/util/Link'
@ -88,8 +87,7 @@ type FlatlistSlice =
key: string key: string
} }
export const FeedsScreen = withAuthRequired( export function FeedsScreen(_props: Props) {
function FeedsScreenImpl(_props: Props) {
const pal = usePalette('default') const pal = usePalette('default')
const {openComposer} = useComposerControls() const {openComposer} = useComposerControls()
const {isMobile, isTabletOrDesktop} = useWebMediaQueries() const {isMobile, isTabletOrDesktop} = useWebMediaQueries()
@ -287,9 +285,7 @@ export const FeedsScreen = withAuthRequired(
for (const page of popularFeeds.pages || []) { for (const page of popularFeeds.pages || []) {
slices = slices.concat( slices = slices.concat(
page.feeds page.feeds
.filter( .filter(feed => !preferences?.feeds?.saved.includes(feed.uri))
feed => !preferences?.feeds?.saved.includes(feed.uri),
)
.map(feed => ({ .map(feed => ({
key: `popularFeed:${feed.uri}`, key: `popularFeed:${feed.uri}`,
type: 'popularFeed', type: 'popularFeed',
@ -516,9 +512,7 @@ export const FeedsScreen = withAuthRequired(
)} )}
</View> </View>
) )
}, }
{isPublic: true},
)
function SavedFeed({feedUri}: {feedUri: string}) { function SavedFeed({feedUri}: {feedUri: string}) {
const pal = usePalette('default') const pal = usePalette('default')

View File

@ -3,7 +3,6 @@ import {View, ActivityIndicator, StyleSheet} from 'react-native'
import {useFocusEffect} from '@react-navigation/native' import {useFocusEffect} from '@react-navigation/native'
import {NativeStackScreenProps, HomeTabNavigatorParams} from 'lib/routes/types' import {NativeStackScreenProps, HomeTabNavigatorParams} from 'lib/routes/types'
import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed' import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {FollowingEmptyState} from 'view/com/posts/FollowingEmptyState' import {FollowingEmptyState} from 'view/com/posts/FollowingEmptyState'
import {FollowingEndOfFeed} from 'view/com/posts/FollowingEndOfFeed' import {FollowingEndOfFeed} from 'view/com/posts/FollowingEndOfFeed'
import {CustomFeedEmptyState} from 'view/com/posts/CustomFeedEmptyState' import {CustomFeedEmptyState} from 'view/com/posts/CustomFeedEmptyState'
@ -17,8 +16,7 @@ import {emitSoftReset} from '#/state/events'
import {useSession} from '#/state/session' import {useSession} from '#/state/session'
type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'> type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'>
export const HomeScreen = withAuthRequired( export function HomeScreen(props: Props) {
function HomeScreenImpl(props: Props) {
const {hasSession} = useSession() const {hasSession} = useSession()
const {data: preferences} = usePreferencesQuery() const {data: preferences} = usePreferencesQuery()
@ -35,11 +33,7 @@ export const HomeScreen = withAuthRequired(
</View> </View>
) )
} }
}, }
{
isPublic: true,
},
)
function HomeScreenPublic() { function HomeScreenPublic() {
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()

View File

@ -4,7 +4,6 @@ import {useFocusEffect, useNavigation} from '@react-navigation/native'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {AtUri} from '@atproto/api' import {AtUri} from '@atproto/api'
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {MyLists} from '#/view/com/lists/MyLists' import {MyLists} from '#/view/com/lists/MyLists'
import {Text} from 'view/com/util/text/Text' import {Text} from 'view/com/util/text/Text'
import {Button} from 'view/com/util/forms/Button' import {Button} from 'view/com/util/forms/Button'
@ -18,8 +17,7 @@ import {useModalControls} from '#/state/modals'
import {Trans} from '@lingui/macro' import {Trans} from '@lingui/macro'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Lists'> type Props = NativeStackScreenProps<CommonNavigatorParams, 'Lists'>
export const ListsScreen = withAuthRequired( export function ListsScreen({}: Props) {
function ListsScreenImpl({}: Props) {
const pal = usePalette('default') const pal = usePalette('default')
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
const {isMobile} = useWebMediaQueries() const {isMobile} = useWebMediaQueries()
@ -83,5 +81,4 @@ export const ListsScreen = withAuthRequired(
<MyLists filter="curate" style={s.flexGrow1} /> <MyLists filter="curate" style={s.flexGrow1} />
</View> </View>
) )
}, }
)

View File

@ -6,7 +6,6 @@ import {
FontAwesomeIconStyle, FontAwesomeIconStyle,
} from '@fortawesome/react-native-fontawesome' } from '@fortawesome/react-native-fontawesome'
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {s} from 'lib/styles' import {s} from 'lib/styles'
import {CenteredView} from '../com/util/Views' import {CenteredView} from '../com/util/Views'
import {ViewHeader} from '../com/util/ViewHeader' import {ViewHeader} from '../com/util/ViewHeader'
@ -21,8 +20,7 @@ import {Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Moderation'> type Props = NativeStackScreenProps<CommonNavigatorParams, 'Moderation'>
export const ModerationScreen = withAuthRequired( export function ModerationScreen({}: Props) {
function Moderation({}: Props) {
const pal = usePalette('default') const pal = usePalette('default')
const {_} = useLingui() const {_} = useLingui()
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
@ -113,8 +111,7 @@ export const ModerationScreen = withAuthRequired(
</Link> </Link>
</CenteredView> </CenteredView>
) )
}, }
)
const styles = StyleSheet.create({ const styles = StyleSheet.create({
desktopContainer: { desktopContainer: {

View File

@ -10,7 +10,6 @@ import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
import {Text} from '../com/util/text/Text' import {Text} from '../com/util/text/Text'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {NativeStackScreenProps} from '@react-navigation/native-stack' import {NativeStackScreenProps} from '@react-navigation/native-stack'
import {CommonNavigatorParams} from 'lib/routes/types' import {CommonNavigatorParams} from 'lib/routes/types'
import {useAnalytics} from 'lib/analytics/analytics' import {useAnalytics} from 'lib/analytics/analytics'
@ -30,8 +29,7 @@ type Props = NativeStackScreenProps<
CommonNavigatorParams, CommonNavigatorParams,
'ModerationBlockedAccounts' 'ModerationBlockedAccounts'
> >
export const ModerationBlockedAccounts = withAuthRequired( export function ModerationBlockedAccounts({}: Props) {
function ModerationBlockedAccountsImpl({}: Props) {
const pal = usePalette('default') const pal = usePalette('default')
const {_} = useLingui() const {_} = useLingui()
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
@ -131,9 +129,9 @@ export const ModerationBlockedAccounts = withAuthRequired(
<View style={[styles.empty, pal.viewLight]}> <View style={[styles.empty, pal.viewLight]}>
<Text type="lg" style={[pal.text, styles.emptyText]}> <Text type="lg" style={[pal.text, styles.emptyText]}>
<Trans> <Trans>
You have not blocked any accounts yet. To block an account, You have not blocked any accounts yet. To block an account, go
go to their profile and selected "Block account" from the to their profile and selected "Block account" from the menu on
menu on their account. their account.
</Trans> </Trans>
</Text> </Text>
</View> </View>
@ -168,8 +166,7 @@ export const ModerationBlockedAccounts = withAuthRequired(
)} )}
</CenteredView> </CenteredView>
) )
}, }
)
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {

View File

@ -4,7 +4,6 @@ import {useFocusEffect, useNavigation} from '@react-navigation/native'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {AtUri} from '@atproto/api' import {AtUri} from '@atproto/api'
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {MyLists} from '#/view/com/lists/MyLists' import {MyLists} from '#/view/com/lists/MyLists'
import {Text} from 'view/com/util/text/Text' import {Text} from 'view/com/util/text/Text'
import {Button} from 'view/com/util/forms/Button' import {Button} from 'view/com/util/forms/Button'
@ -17,8 +16,7 @@ import {useSetMinimalShellMode} from '#/state/shell'
import {useModalControls} from '#/state/modals' import {useModalControls} from '#/state/modals'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'ModerationModlists'> type Props = NativeStackScreenProps<CommonNavigatorParams, 'ModerationModlists'>
export const ModerationModlistsScreen = withAuthRequired( export function ModerationModlistsScreen({}: Props) {
function ModerationModlistsScreenImpl({}: Props) {
const pal = usePalette('default') const pal = usePalette('default')
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
const {isMobile} = useWebMediaQueries() const {isMobile} = useWebMediaQueries()
@ -82,5 +80,4 @@ export const ModerationModlistsScreen = withAuthRequired(
<MyLists filter="mod" style={s.flexGrow1} /> <MyLists filter="mod" style={s.flexGrow1} />
</View> </View>
) )
}, }
)

View File

@ -10,7 +10,6 @@ import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
import {Text} from '../com/util/text/Text' import {Text} from '../com/util/text/Text'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {NativeStackScreenProps} from '@react-navigation/native-stack' import {NativeStackScreenProps} from '@react-navigation/native-stack'
import {CommonNavigatorParams} from 'lib/routes/types' import {CommonNavigatorParams} from 'lib/routes/types'
import {useAnalytics} from 'lib/analytics/analytics' import {useAnalytics} from 'lib/analytics/analytics'
@ -30,8 +29,7 @@ type Props = NativeStackScreenProps<
CommonNavigatorParams, CommonNavigatorParams,
'ModerationMutedAccounts' 'ModerationMutedAccounts'
> >
export const ModerationMutedAccounts = withAuthRequired( export function ModerationMutedAccounts({}: Props) {
function ModerationMutedAccountsImpl({}: Props) {
const pal = usePalette('default') const pal = usePalette('default')
const {_} = useLingui() const {_} = useLingui()
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
@ -130,9 +128,9 @@ export const ModerationMutedAccounts = withAuthRequired(
<View style={[styles.empty, pal.viewLight]}> <View style={[styles.empty, pal.viewLight]}>
<Text type="lg" style={[pal.text, styles.emptyText]}> <Text type="lg" style={[pal.text, styles.emptyText]}>
<Trans> <Trans>
You have not muted any accounts yet. To mute an account, go You have not muted any accounts yet. To mute an account, go to
to their profile and selected "Mute account" from the menu their profile and selected "Mute account" from the menu on
on their account. their account.
</Trans> </Trans>
</Text> </Text>
</View> </View>
@ -167,8 +165,7 @@ export const ModerationMutedAccounts = withAuthRequired(
)} )}
</CenteredView> </CenteredView>
) )
}, }
)
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {

View File

@ -6,7 +6,6 @@ import {
NativeStackScreenProps, NativeStackScreenProps,
NotificationsTabNavigatorParams, NotificationsTabNavigatorParams,
} from 'lib/routes/types' } from 'lib/routes/types'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {ViewHeader} from '../com/util/ViewHeader' import {ViewHeader} from '../com/util/ViewHeader'
import {Feed} from '../com/notifications/Feed' import {Feed} from '../com/notifications/Feed'
import {TextLink} from 'view/com/util/Link' import {TextLink} from 'view/com/util/Link'
@ -28,8 +27,7 @@ type Props = NativeStackScreenProps<
NotificationsTabNavigatorParams, NotificationsTabNavigatorParams,
'Notifications' 'Notifications'
> >
export const NotificationsScreen = withAuthRequired( export function NotificationsScreen({}: Props) {
function NotificationsScreenImpl({}: Props) {
const {_} = useLingui() const {_} = useLingui()
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll() const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll()
@ -125,5 +123,4 @@ export const NotificationsScreen = withAuthRequired(
)} )}
</View> </View>
) )
}, }
)

View File

@ -2,7 +2,6 @@ import React from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import {useFocusEffect} from '@react-navigation/native' import {useFocusEffect} from '@react-navigation/native'
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {ViewHeader} from '../com/util/ViewHeader' import {ViewHeader} from '../com/util/ViewHeader'
import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy' import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy'
import {makeRecordUri} from 'lib/strings/url-helpers' import {makeRecordUri} from 'lib/strings/url-helpers'
@ -11,8 +10,7 @@ import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostLikedBy'> type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostLikedBy'>
export const PostLikedByScreen = withAuthRequired( export const PostLikedByScreen = ({route}: Props) => {
({route}: Props) => {
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
const {name, rkey} = route.params const {name, rkey} = route.params
const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey) const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey)
@ -30,6 +28,4 @@ export const PostLikedByScreen = withAuthRequired(
<PostLikedByComponent uri={uri} /> <PostLikedByComponent uri={uri} />
</View> </View>
) )
}, }
{isPublic: true},
)

View File

@ -1,7 +1,6 @@
import React from 'react' import React from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import {useFocusEffect} from '@react-navigation/native' import {useFocusEffect} from '@react-navigation/native'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
import {ViewHeader} from '../com/util/ViewHeader' import {ViewHeader} from '../com/util/ViewHeader'
import {PostRepostedBy as PostRepostedByComponent} from '../com/post-thread/PostRepostedBy' import {PostRepostedBy as PostRepostedByComponent} from '../com/post-thread/PostRepostedBy'
@ -11,8 +10,7 @@ import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro' import {msg} from '@lingui/macro'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostRepostedBy'> type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostRepostedBy'>
export const PostRepostedByScreen = withAuthRequired( export const PostRepostedByScreen = ({route}: Props) => {
({route}: Props) => {
const {name, rkey} = route.params const {name, rkey} = route.params
const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey) const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey)
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
@ -30,6 +28,4 @@ export const PostRepostedByScreen = withAuthRequired(
<PostRepostedByComponent uri={uri} /> <PostRepostedByComponent uri={uri} />
</View> </View>
) )
}, }
{isPublic: true},
)

View File

@ -5,7 +5,6 @@ import {useFocusEffect} from '@react-navigation/native'
import {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
import {makeRecordUri} from 'lib/strings/url-helpers' import {makeRecordUri} from 'lib/strings/url-helpers'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {ViewHeader} from '../com/util/ViewHeader' import {ViewHeader} from '../com/util/ViewHeader'
import {PostThread as PostThreadComponent} from '../com/post-thread/PostThread' import {PostThread as PostThreadComponent} from '../com/post-thread/PostThread'
import {ComposePrompt} from 'view/com/composer/Prompt' import {ComposePrompt} from 'view/com/composer/Prompt'
@ -27,8 +26,7 @@ import {CenteredView} from '../com/util/Views'
import {useComposerControls} from '#/state/shell/composer' import {useComposerControls} from '#/state/shell/composer'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostThread'> type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostThread'>
export const PostThreadScreen = withAuthRequired( export function PostThreadScreen({route}: Props) {
function PostThreadScreenImpl({route}: Props) {
const queryClient = useQueryClient() const queryClient = useQueryClient()
const {_} = useLingui() const {_} = useLingui()
const {fabMinimalShellTransform} = useMinimalShellMode() const {fabMinimalShellTransform} = useMinimalShellMode()
@ -103,9 +101,7 @@ export const PostThreadScreen = withAuthRequired(
)} )}
</View> </View>
) )
}, }
{isPublic: true},
)
const styles = StyleSheet.create({ const styles = StyleSheet.create({
prompt: { prompt: {

View File

@ -5,7 +5,6 @@ import {AppBskyActorDefs, moderateProfile, ModerationOpts} from '@atproto/api'
import {msg} from '@lingui/macro' import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {ViewSelectorHandle} from '../com/util/ViewSelector' import {ViewSelectorHandle} from '../com/util/ViewSelector'
import {CenteredView, FlatList} from '../com/util/Views' import {CenteredView, FlatList} from '../com/util/Views'
import {ScreenHider} from 'view/com/util/moderation/ScreenHider' import {ScreenHider} from 'view/com/util/moderation/ScreenHider'
@ -43,8 +42,7 @@ interface SectionRef {
} }
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Profile'> type Props = NativeStackScreenProps<CommonNavigatorParams, 'Profile'>
export const ProfileScreen = withAuthRequired( export function ProfileScreen({route}: Props) {
function ProfileScreenImpl({route}: Props) {
const {currentAccount} = useSession() const {currentAccount} = useSession()
const name = const name =
route.params.name === 'me' ? currentAccount?.did : route.params.name route.params.name === 'me' ? currentAccount?.did : route.params.name
@ -115,11 +113,7 @@ export const ProfileScreen = withAuthRequired(
/> />
</CenteredView> </CenteredView>
) )
}, }
{
isPublic: true,
},
)
function ProfileScreenLoaded({ function ProfileScreenLoaded({
profile: profileUnshadowed, profile: profileUnshadowed,

View File

@ -16,7 +16,6 @@ import {CommonNavigatorParams} from 'lib/routes/types'
import {makeRecordUri} from 'lib/strings/url-helpers' import {makeRecordUri} from 'lib/strings/url-helpers'
import {colors, s} from 'lib/styles' import {colors, s} from 'lib/styles'
import {FeedDescriptor} from '#/state/queries/post-feed' import {FeedDescriptor} from '#/state/queries/post-feed'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {PagerWithHeader} from 'view/com/pager/PagerWithHeader' import {PagerWithHeader} from 'view/com/pager/PagerWithHeader'
import {ProfileSubpageHeader} from 'view/com/profile/ProfileSubpageHeader' import {ProfileSubpageHeader} from 'view/com/profile/ProfileSubpageHeader'
import {Feed} from 'view/com/posts/Feed' import {Feed} from 'view/com/posts/Feed'
@ -69,8 +68,7 @@ interface SectionRef {
} }
type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFeed'> type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFeed'>
export const ProfileFeedScreen = withAuthRequired( export function ProfileFeedScreen(props: Props) {
function ProfileFeedScreenImpl(props: Props) {
const {rkey, name: handleOrDid} = props.route.params const {rkey, name: handleOrDid} = props.route.params
const pal = usePalette('default') const pal = usePalette('default')
@ -128,11 +126,7 @@ export const ProfileFeedScreen = withAuthRequired(
</View> </View>
</CenteredView> </CenteredView>
) )
}, }
{
isPublic: true,
},
)
function ProfileFeedScreenIntermediate({feedUri}: {feedUri: string}) { function ProfileFeedScreenIntermediate({feedUri}: {feedUri: string}) {
const {data: preferences} = usePreferencesQuery() const {data: preferences} = usePreferencesQuery()

View File

@ -2,7 +2,6 @@ import React from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import {useFocusEffect} from '@react-navigation/native' import {useFocusEffect} from '@react-navigation/native'
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {ViewHeader} from '../com/util/ViewHeader' import {ViewHeader} from '../com/util/ViewHeader'
import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy' import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy'
import {makeRecordUri} from 'lib/strings/url-helpers' import {makeRecordUri} from 'lib/strings/url-helpers'
@ -11,8 +10,7 @@ import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro' import {msg} from '@lingui/macro'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFeedLikedBy'> type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFeedLikedBy'>
export const ProfileFeedLikedByScreen = withAuthRequired( export const ProfileFeedLikedByScreen = ({route}: Props) => {
({route}: Props) => {
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
const {name, rkey} = route.params const {name, rkey} = route.params
const uri = makeRecordUri(name, 'app.bsky.feed.generator', rkey) const uri = makeRecordUri(name, 'app.bsky.feed.generator', rkey)
@ -30,6 +28,4 @@ export const ProfileFeedLikedByScreen = withAuthRequired(
<PostLikedByComponent uri={uri} /> <PostLikedByComponent uri={uri} />
</View> </View>
) )
}, }
{isPublic: true},
)

View File

@ -2,7 +2,6 @@ import React from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import {useFocusEffect} from '@react-navigation/native' import {useFocusEffect} from '@react-navigation/native'
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {ViewHeader} from '../com/util/ViewHeader' import {ViewHeader} from '../com/util/ViewHeader'
import {ProfileFollowers as ProfileFollowersComponent} from '../com/profile/ProfileFollowers' import {ProfileFollowers as ProfileFollowersComponent} from '../com/profile/ProfileFollowers'
import {useSetMinimalShellMode} from '#/state/shell' import {useSetMinimalShellMode} from '#/state/shell'
@ -10,8 +9,7 @@ import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro' import {msg} from '@lingui/macro'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFollowers'> type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFollowers'>
export const ProfileFollowersScreen = withAuthRequired( export const ProfileFollowersScreen = ({route}: Props) => {
({route}: Props) => {
const {name} = route.params const {name} = route.params
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
const {_} = useLingui() const {_} = useLingui()
@ -28,6 +26,4 @@ export const ProfileFollowersScreen = withAuthRequired(
<ProfileFollowersComponent name={name} /> <ProfileFollowersComponent name={name} />
</View> </View>
) )
}, }
{isPublic: true},
)

View File

@ -2,7 +2,6 @@ import React from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import {useFocusEffect} from '@react-navigation/native' import {useFocusEffect} from '@react-navigation/native'
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {ViewHeader} from '../com/util/ViewHeader' import {ViewHeader} from '../com/util/ViewHeader'
import {ProfileFollows as ProfileFollowsComponent} from '../com/profile/ProfileFollows' import {ProfileFollows as ProfileFollowsComponent} from '../com/profile/ProfileFollows'
import {useSetMinimalShellMode} from '#/state/shell' import {useSetMinimalShellMode} from '#/state/shell'
@ -10,8 +9,7 @@ import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro' import {msg} from '@lingui/macro'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFollows'> type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFollows'>
export const ProfileFollowsScreen = withAuthRequired( export const ProfileFollowsScreen = ({route}: Props) => {
({route}: Props) => {
const {name} = route.params const {name} = route.params
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
const {_} = useLingui() const {_} = useLingui()
@ -28,6 +26,4 @@ export const ProfileFollowsScreen = withAuthRequired(
<ProfileFollowsComponent name={name} /> <ProfileFollowsComponent name={name} />
</View> </View>
) )
}, }
{isPublic: true},
)

View File

@ -12,7 +12,6 @@ import {useNavigation} from '@react-navigation/native'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {AppBskyGraphDefs, AtUri, RichText as RichTextAPI} from '@atproto/api' import {AppBskyGraphDefs, AtUri, RichText as RichTextAPI} from '@atproto/api'
import {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {PagerWithHeader} from 'view/com/pager/PagerWithHeader' import {PagerWithHeader} from 'view/com/pager/PagerWithHeader'
import {ProfileSubpageHeader} from 'view/com/profile/ProfileSubpageHeader' import {ProfileSubpageHeader} from 'view/com/profile/ProfileSubpageHeader'
import {Feed} from 'view/com/posts/Feed' import {Feed} from 'view/com/posts/Feed'
@ -64,8 +63,7 @@ interface SectionRef {
} }
type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileList'> type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileList'>
export const ProfileListScreen = withAuthRequired( export function ProfileListScreen(props: Props) {
function ProfileListScreenImpl(props: Props) {
const {name: handleOrDid, rkey} = props.route.params const {name: handleOrDid, rkey} = props.route.params
const {data: resolvedUri, error: resolveError} = useResolveUriQuery( const {data: resolvedUri, error: resolveError} = useResolveUriQuery(
AtUri.make(handleOrDid, 'app.bsky.graph.list', rkey).toString(), AtUri.make(handleOrDid, 'app.bsky.graph.list', rkey).toString(),
@ -98,8 +96,7 @@ export const ProfileListScreen = withAuthRequired(
</View> </View>
</CenteredView> </CenteredView>
) )
}, }
)
function ProfileListScreenLoaded({ function ProfileListScreenLoaded({
route, route,

View File

@ -14,7 +14,6 @@ import {useAnalytics} from 'lib/analytics/analytics'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
import {CommonNavigatorParams} from 'lib/routes/types' import {CommonNavigatorParams} from 'lib/routes/types'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {ViewHeader} from 'view/com/util/ViewHeader' import {ViewHeader} from 'view/com/util/ViewHeader'
import {ScrollView, CenteredView} from 'view/com/util/Views' import {ScrollView, CenteredView} from 'view/com/util/Views'
import {Text} from 'view/com/util/text/Text' import {Text} from 'view/com/util/text/Text'
@ -51,7 +50,7 @@ const HITSLOP_BOTTOM = {
} }
type Props = NativeStackScreenProps<CommonNavigatorParams, 'SavedFeeds'> type Props = NativeStackScreenProps<CommonNavigatorParams, 'SavedFeeds'>
export const SavedFeeds = withAuthRequired(function SavedFeedsImpl({}: Props) { export function SavedFeeds({}: Props) {
const pal = usePalette('default') const pal = usePalette('default')
const {_} = useLingui() const {_} = useLingui()
const {isMobile, isTabletOrDesktop} = useWebMediaQueries() const {isMobile, isTabletOrDesktop} = useWebMediaQueries()
@ -147,7 +146,7 @@ export const SavedFeeds = withAuthRequired(function SavedFeedsImpl({}: Props) {
</ScrollView> </ScrollView>
</CenteredView> </CenteredView>
) )
}) }
function ListItem({ function ListItem({
feedUri, feedUri,

View File

@ -1,6 +1,3 @@
import {withAuthRequired} from '#/view/com/auth/withAuthRequired'
import {SearchScreenMobile} from '#/view/screens/Search/Search' import {SearchScreenMobile} from '#/view/screens/Search/Search'
export const SearchScreen = withAuthRequired(SearchScreenMobile, { export const SearchScreen = SearchScreenMobile
isPublic: true,
})

View File

@ -1,6 +1,3 @@
import {withAuthRequired} from '#/view/com/auth/withAuthRequired'
import {SearchScreenDesktop} from '#/view/screens/Search/Search' import {SearchScreenDesktop} from '#/view/screens/Search/Search'
export const SearchScreen = withAuthRequired(SearchScreenDesktop, { export const SearchScreen = SearchScreenDesktop
isPublic: true,
})

View File

@ -20,7 +20,6 @@ import {
FontAwesomeIconStyle, FontAwesomeIconStyle,
} from '@fortawesome/react-native-fontawesome' } from '@fortawesome/react-native-fontawesome'
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import * as AppInfo from 'lib/app-info' import * as AppInfo from 'lib/app-info'
import {s, colors} from 'lib/styles' import {s, colors} from 'lib/styles'
import {ScrollView} from '../com/util/Views' import {ScrollView} from '../com/util/Views'
@ -141,7 +140,7 @@ function SettingsAccountCard({account}: {account: SessionAccount}) {
} }
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Settings'> type Props = NativeStackScreenProps<CommonNavigatorParams, 'Settings'>
export const SettingsScreen = withAuthRequired(function Settings({}: Props) { export function SettingsScreen({}: Props) {
const queryClient = useQueryClient() const queryClient = useQueryClient()
const colorMode = useColorMode() const colorMode = useColorMode()
const setColorMode = useSetColorMode() const setColorMode = useSetColorMode()
@ -731,7 +730,7 @@ export const SettingsScreen = withAuthRequired(function Settings({}: Props) {
</ScrollView> </ScrollView>
</View> </View>
) )
}) }
function EmailConfirmationNotice() { function EmailConfirmationNotice() {
const pal = usePalette('default') const pal = usePalette('default')

View File

@ -0,0 +1,150 @@
import * as React from 'react'
import {View} from 'react-native'
// Based on @react-navigation/native-stack/src/createNativeStackNavigator.ts
// MIT License
// Copyright (c) 2017 React Navigation Contributors
import {
createNavigatorFactory,
EventArg,
ParamListBase,
StackActionHelpers,
StackActions,
StackNavigationState,
StackRouter,
StackRouterOptions,
useNavigationBuilder,
} from '@react-navigation/native'
import type {
NativeStackNavigationEventMap,
NativeStackNavigationOptions,
} from '@react-navigation/native-stack'
import type {NativeStackNavigatorProps} from '@react-navigation/native-stack/src/types'
import {NativeStackView} from '@react-navigation/native-stack'
import {BottomBarWeb} from './bottom-bar/BottomBarWeb'
import {DesktopLeftNav} from './desktop/LeftNav'
import {DesktopRightNav} from './desktop/RightNav'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {useOnboardingState} from '#/state/shell'
import {
useLoggedOutView,
useLoggedOutViewControls,
} from '#/state/shell/logged-out'
import {useSession} from '#/state/session'
import {isWeb} from 'platform/detection'
import {LoggedOut} from '../com/auth/LoggedOut'
import {Onboarding} from '../com/auth/Onboarding'
type NativeStackNavigationOptionsWithAuth = NativeStackNavigationOptions & {
requireAuth?: boolean
}
function NativeStackNavigator({
id,
initialRouteName,
children,
screenListeners,
screenOptions,
...rest
}: NativeStackNavigatorProps) {
// --- this is copy and pasted from the original native stack navigator ---
const {state, descriptors, navigation, NavigationContent} =
useNavigationBuilder<
StackNavigationState<ParamListBase>,
StackRouterOptions,
StackActionHelpers<ParamListBase>,
NativeStackNavigationOptionsWithAuth,
NativeStackNavigationEventMap
>(StackRouter, {
id,
initialRouteName,
children,
screenListeners,
screenOptions,
})
React.useEffect(
() =>
// @ts-expect-error: there may not be a tab navigator in parent
navigation?.addListener?.('tabPress', (e: any) => {
const isFocused = navigation.isFocused()
// Run the operation in the next frame so we're sure all listeners have been run
// This is necessary to know if preventDefault() has been called
requestAnimationFrame(() => {
if (
state.index > 0 &&
isFocused &&
!(e as EventArg<'tabPress', true>).defaultPrevented
) {
// When user taps on already focused tab and we're inside the tab,
// reset the stack to replicate native behaviour
navigation.dispatch({
...StackActions.popToTop(),
target: state.key,
})
}
})
}),
[navigation, state.index, state.key],
)
// --- our custom logic starts here ---
const {hasSession} = useSession()
const activeRoute = state.routes[state.index]
const activeDescriptor = descriptors[activeRoute.key]
const activeRouteRequiresAuth = activeDescriptor.options.requireAuth ?? false
const onboardingState = useOnboardingState()
const {showLoggedOut} = useLoggedOutView()
const {setShowLoggedOut} = useLoggedOutViewControls()
const {isMobile} = useWebMediaQueries()
if (activeRouteRequiresAuth && !hasSession) {
return <LoggedOut />
}
if (showLoggedOut) {
return <LoggedOut onDismiss={() => setShowLoggedOut(false)} />
}
if (onboardingState.isActive) {
return <Onboarding />
}
const newDescriptors: typeof descriptors = {}
for (let key in descriptors) {
const descriptor = descriptors[key]
const requireAuth = descriptor.options.requireAuth ?? false
newDescriptors[key] = {
...descriptor,
render() {
if (requireAuth && !hasSession) {
return <View />
} else {
return descriptor.render()
}
},
}
}
return (
<NavigationContent>
<NativeStackView
{...rest}
state={state}
navigation={navigation}
descriptors={newDescriptors}
/>
{isWeb && isMobile && <BottomBarWeb />}
{isWeb && !isMobile && (
<>
<DesktopLeftNav />
<DesktopRightNav />
</>
)}
</NavigationContent>
)
}
export const createNativeStackNavigatorWithAuth = createNavigatorFactory<
StackNavigationState<ParamListBase>,
NativeStackNavigationOptionsWithAuth,
NativeStackNavigationEventMap,
typeof NativeStackNavigator
>(NativeStackNavigator)

View File

@ -1,7 +1,5 @@
import React, {useEffect} from 'react' import React, {useEffect} from 'react'
import {View, StyleSheet, TouchableOpacity} from 'react-native' import {View, StyleSheet, TouchableOpacity} from 'react-native'
import {DesktopLeftNav} from './desktop/LeftNav'
import {DesktopRightNav} from './desktop/RightNav'
import {ErrorBoundary} from '../com/util/ErrorBoundary' import {ErrorBoundary} from '../com/util/ErrorBoundary'
import {Lightbox} from '../com/lightbox/Lightbox' import {Lightbox} from '../com/lightbox/Lightbox'
import {ModalsContainer} from '../com/modals/Modal' import {ModalsContainer} from '../com/modals/Modal'
@ -11,27 +9,19 @@ import {s, colors} from 'lib/styles'
import {RoutesContainer, FlatNavigator} from '../../Navigation' import {RoutesContainer, FlatNavigator} from '../../Navigation'
import {DrawerContent} from './Drawer' import {DrawerContent} from './Drawer'
import {useWebMediaQueries} from '../../lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from '../../lib/hooks/useWebMediaQueries'
import {BottomBarWeb} from './bottom-bar/BottomBarWeb'
import {useNavigation} from '@react-navigation/native' import {useNavigation} from '@react-navigation/native'
import {NavigationProp} from 'lib/routes/types' import {NavigationProp} from 'lib/routes/types'
import {useAuxClick} from 'lib/hooks/useAuxClick' import {useAuxClick} from 'lib/hooks/useAuxClick'
import {t} from '@lingui/macro' import {t} from '@lingui/macro'
import { import {useIsDrawerOpen, useSetDrawerOpen} from '#/state/shell'
useIsDrawerOpen,
useSetDrawerOpen,
useOnboardingState,
} from '#/state/shell'
import {useCloseAllActiveElements} from '#/state/util' import {useCloseAllActiveElements} from '#/state/util'
import {useLoggedOutView} from '#/state/shell/logged-out'
function ShellInner() { function ShellInner() {
const isDrawerOpen = useIsDrawerOpen() const isDrawerOpen = useIsDrawerOpen()
const setDrawerOpen = useSetDrawerOpen() const setDrawerOpen = useSetDrawerOpen()
const onboardingState = useOnboardingState() const {isDesktop} = useWebMediaQueries()
const {isDesktop, isMobile} = useWebMediaQueries()
const navigator = useNavigation<NavigationProp>() const navigator = useNavigation<NavigationProp>()
const closeAllActiveElements = useCloseAllActiveElements() const closeAllActiveElements = useCloseAllActiveElements()
const {showLoggedOut} = useLoggedOutView()
useAuxClick() useAuxClick()
@ -42,8 +32,6 @@ function ShellInner() {
return unsubscribe return unsubscribe
}, [navigator, closeAllActiveElements]) }, [navigator, closeAllActiveElements])
const showBottomBar = isMobile && !onboardingState.isActive
const showSideNavs = !isMobile && !onboardingState.isActive && !showLoggedOut
return ( return (
<View style={[s.hContentRegion, {overflow: 'hidden'}]}> <View style={[s.hContentRegion, {overflow: 'hidden'}]}>
<View style={s.hContentRegion}> <View style={s.hContentRegion}>
@ -51,22 +39,9 @@ function ShellInner() {
<FlatNavigator /> <FlatNavigator />
</ErrorBoundary> </ErrorBoundary>
</View> </View>
{showSideNavs && (
<>
<DesktopLeftNav />
<DesktopRightNav />
</>
)}
<Composer winHeight={0} /> <Composer winHeight={0} />
{showBottomBar && <BottomBarWeb />}
<ModalsContainer /> <ModalsContainer />
<Lightbox /> <Lightbox />
{!isDesktop && isDrawerOpen && ( {!isDesktop && isDrawerOpen && (
<TouchableOpacity <TouchableOpacity
onPress={() => setDrawerOpen(false)} onPress={() => setDrawerOpen(false)}