about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/App.native.tsx35
-rw-r--r--src/App.web.tsx35
-rw-r--r--src/Navigation.tsx48
-rw-r--r--src/state/shell/index.tsx31
-rw-r--r--src/view/com/auth/withAuthRequired.tsx94
-rw-r--r--src/view/screens/AppPasswords.tsx251
-rw-r--r--src/view/screens/Feeds.tsx748
-rw-r--r--src/view/screens/Home.tsx42
-rw-r--r--src/view/screens/Lists.tsx125
-rw-r--r--src/view/screens/Moderation.tsx181
-rw-r--r--src/view/screens/ModerationBlockedAccounts.tsx265
-rw-r--r--src/view/screens/ModerationModlists.tsx125
-rw-r--r--src/view/screens/ModerationMutedAccounts.tsx263
-rw-r--r--src/view/screens/Notifications.tsx185
-rw-r--r--src/view/screens/PostLikedBy.tsx38
-rw-r--r--src/view/screens/PostRepostedBy.tsx38
-rw-r--r--src/view/screens/PostThread.tsx144
-rw-r--r--src/view/screens/Profile.tsx126
-rw-r--r--src/view/screens/ProfileFeed.tsx106
-rw-r--r--src/view/screens/ProfileFeedLikedBy.tsx38
-rw-r--r--src/view/screens/ProfileFollowers.tsx36
-rw-r--r--src/view/screens/ProfileFollows.tsx36
-rw-r--r--src/view/screens/ProfileList.tsx63
-rw-r--r--src/view/screens/SavedFeeds.tsx5
-rw-r--r--src/view/screens/Search/index.tsx5
-rw-r--r--src/view/screens/Search/index.web.tsx5
-rw-r--r--src/view/screens/Settings.tsx5
-rw-r--r--src/view/shell/createNativeStackNavigatorWithAuth.tsx150
-rw-r--r--src/view/shell/index.web.tsx29
29 files changed, 1607 insertions, 1645 deletions
diff --git a/src/App.native.tsx b/src/App.native.tsx
index b9f9519c9..64c7e718f 100644
--- a/src/App.native.tsx
+++ b/src/App.native.tsx
@@ -28,6 +28,7 @@ import {Provider as LightboxStateProvider} from 'state/lightbox'
 import {Provider as MutedThreadsProvider} from 'state/muted-threads'
 import {Provider as InvitesStateProvider} from 'state/invites'
 import {Provider as PrefsStateProvider} from 'state/preferences'
+import {Provider as LoggedOutViewProvider} from 'state/shell/logged-out'
 import I18nProvider from './locale/i18nProvider'
 import {
   Provider as SessionProvider,
@@ -42,7 +43,7 @@ SplashScreen.preventAutoHideAsync()
 
 function InnerApp() {
   const colorMode = useColorMode()
-  const {isInitialLoad} = useSession()
+  const {isInitialLoad, currentAccount} = useSession()
   const {resumeSession} = useSessionApi()
 
   // init
@@ -69,19 +70,25 @@ function InnerApp() {
    */
 
   return (
-    <UnreadNotifsProvider>
-      <ThemeProvider theme={colorMode}>
-        <analytics.Provider>
-          {/* All components should be within this provider */}
-          <RootSiblingParent>
-            <GestureHandlerRootView style={s.h100pct}>
-              <TestCtrls />
-              <Shell />
-            </GestureHandlerRootView>
-          </RootSiblingParent>
-        </analytics.Provider>
-      </ThemeProvider>
-    </UnreadNotifsProvider>
+    <React.Fragment
+      // Resets the entire tree below when it changes:
+      key={currentAccount?.did}>
+      <LoggedOutViewProvider>
+        <UnreadNotifsProvider>
+          <ThemeProvider theme={colorMode}>
+            <analytics.Provider>
+              {/* All components should be within this provider */}
+              <RootSiblingParent>
+                <GestureHandlerRootView style={s.h100pct}>
+                  <TestCtrls />
+                  <Shell />
+                </GestureHandlerRootView>
+              </RootSiblingParent>
+            </analytics.Provider>
+          </ThemeProvider>
+        </UnreadNotifsProvider>
+      </LoggedOutViewProvider>
+    </React.Fragment>
   )
 }
 
diff --git a/src/App.web.tsx b/src/App.web.tsx
index fa0b225c0..e939dda6d 100644
--- a/src/App.web.tsx
+++ b/src/App.web.tsx
@@ -22,6 +22,7 @@ import {Provider as LightboxStateProvider} from 'state/lightbox'
 import {Provider as MutedThreadsProvider} from 'state/muted-threads'
 import {Provider as InvitesStateProvider} from 'state/invites'
 import {Provider as PrefsStateProvider} from 'state/preferences'
+import {Provider as LoggedOutViewProvider} from 'state/shell/logged-out'
 import I18nProvider from './locale/i18nProvider'
 import {
   Provider as SessionProvider,
@@ -34,7 +35,7 @@ import * as persisted from '#/state/persisted'
 enableFreeze(true)
 
 function InnerApp() {
-  const {isInitialLoad} = useSession()
+  const {isInitialLoad, currentAccount} = useSession()
   const {resumeSession} = useSessionApi()
   const colorMode = useColorMode()
 
@@ -57,19 +58,25 @@ function InnerApp() {
    */
 
   return (
-    <UnreadNotifsProvider>
-      <ThemeProvider theme={colorMode}>
-        <analytics.Provider>
-          {/* All components should be within this provider */}
-          <RootSiblingParent>
-            <SafeAreaProvider>
-              <Shell />
-            </SafeAreaProvider>
-          </RootSiblingParent>
-          <ToastContainer />
-        </analytics.Provider>
-      </ThemeProvider>
-    </UnreadNotifsProvider>
+    <React.Fragment
+      // Resets the entire tree below when it changes:
+      key={currentAccount?.did}>
+      <LoggedOutViewProvider>
+        <UnreadNotifsProvider>
+          <ThemeProvider theme={colorMode}>
+            <analytics.Provider>
+              {/* All components should be within this provider */}
+              <RootSiblingParent>
+                <SafeAreaProvider>
+                  <Shell />
+                </SafeAreaProvider>
+              </RootSiblingParent>
+              <ToastContainer />
+            </analytics.Provider>
+          </ThemeProvider>
+        </UnreadNotifsProvider>
+      </LoggedOutViewProvider>
+    </React.Fragment>
   )
 }
 
diff --git a/src/Navigation.tsx b/src/Navigation.tsx
index fb88dc84f..4718349b5 100644
--- a/src/Navigation.tsx
+++ b/src/Navigation.tsx
@@ -9,7 +9,6 @@ import {
   DefaultTheme,
   DarkTheme,
 } from '@react-navigation/native'
-import {createNativeStackNavigator} from '@react-navigation/native-stack'
 import {
   BottomTabBarProps,
   createBottomTabNavigator,
@@ -69,16 +68,18 @@ import {ModerationBlockedAccounts} from 'view/screens/ModerationBlockedAccounts'
 import {SavedFeeds} from 'view/screens/SavedFeeds'
 import {PreferencesHomeFeed} from 'view/screens/PreferencesHomeFeed'
 import {PreferencesThreads} from 'view/screens/PreferencesThreads'
+import {createNativeStackNavigatorWithAuth} from './view/shell/createNativeStackNavigatorWithAuth'
 
 const navigationRef = createNavigationContainerRef<AllNavigatorParams>()
 
-const HomeTab = createNativeStackNavigator<HomeTabNavigatorParams>()
-const SearchTab = createNativeStackNavigator<SearchTabNavigatorParams>()
-const FeedsTab = createNativeStackNavigator<FeedsTabNavigatorParams>()
+const HomeTab = createNativeStackNavigatorWithAuth<HomeTabNavigatorParams>()
+const SearchTab = createNativeStackNavigatorWithAuth<SearchTabNavigatorParams>()
+const FeedsTab = createNativeStackNavigatorWithAuth<FeedsTabNavigatorParams>()
 const NotificationsTab =
-  createNativeStackNavigator<NotificationsTabNavigatorParams>()
-const MyProfileTab = createNativeStackNavigator<MyProfileTabNavigatorParams>()
-const Flat = createNativeStackNavigator<FlatNavigatorParams>()
+  createNativeStackNavigatorWithAuth<NotificationsTabNavigatorParams>()
+const MyProfileTab =
+  createNativeStackNavigatorWithAuth<MyProfileTabNavigatorParams>()
+const Flat = createNativeStackNavigatorWithAuth<FlatNavigatorParams>()
 const Tab = createBottomTabNavigator<BottomTabNavigatorParams>()
 
 /**
@@ -97,37 +98,37 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
       <Stack.Screen
         name="Lists"
         component={ListsScreen}
-        options={{title: title('Lists')}}
+        options={{title: title('Lists'), requireAuth: true}}
       />
       <Stack.Screen
         name="Moderation"
         getComponent={() => ModerationScreen}
-        options={{title: title('Moderation')}}
+        options={{title: title('Moderation'), requireAuth: true}}
       />
       <Stack.Screen
         name="ModerationModlists"
         getComponent={() => ModerationModlistsScreen}
-        options={{title: title('Moderation Lists')}}
+        options={{title: title('Moderation Lists'), requireAuth: true}}
       />
       <Stack.Screen
         name="ModerationMutedAccounts"
         getComponent={() => ModerationMutedAccounts}
-        options={{title: title('Muted Accounts')}}
+        options={{title: title('Muted Accounts'), requireAuth: true}}
       />
       <Stack.Screen
         name="ModerationBlockedAccounts"
         getComponent={() => ModerationBlockedAccounts}
-        options={{title: title('Blocked Accounts')}}
+        options={{title: title('Blocked Accounts'), requireAuth: true}}
       />
       <Stack.Screen
         name="Settings"
         getComponent={() => SettingsScreen}
-        options={{title: title('Settings')}}
+        options={{title: title('Settings'), requireAuth: true}}
       />
       <Stack.Screen
         name="LanguageSettings"
         getComponent={() => LanguageSettingsScreen}
-        options={{title: title('Language Settings')}}
+        options={{title: title('Language Settings'), requireAuth: true}}
       />
       <Stack.Screen
         name="Profile"
@@ -154,7 +155,7 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
       <Stack.Screen
         name="ProfileList"
         getComponent={() => ProfileListScreen}
-        options={{title: title('List')}}
+        options={{title: title('List'), requireAuth: true}}
       />
       <Stack.Screen
         name="PostThread"
@@ -184,12 +185,12 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
       <Stack.Screen
         name="Debug"
         getComponent={() => DebugScreen}
-        options={{title: title('Debug')}}
+        options={{title: title('Debug'), requireAuth: true}}
       />
       <Stack.Screen
         name="Log"
         getComponent={() => LogScreen}
-        options={{title: title('Log')}}
+        options={{title: title('Log'), requireAuth: true}}
       />
       <Stack.Screen
         name="Support"
@@ -219,22 +220,22 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
       <Stack.Screen
         name="AppPasswords"
         getComponent={() => AppPasswords}
-        options={{title: title('App Passwords')}}
+        options={{title: title('App Passwords'), requireAuth: true}}
       />
       <Stack.Screen
         name="SavedFeeds"
         getComponent={() => SavedFeeds}
-        options={{title: title('Edit My Feeds')}}
+        options={{title: title('Edit My Feeds'), requireAuth: true}}
       />
       <Stack.Screen
         name="PreferencesHomeFeed"
         getComponent={() => PreferencesHomeFeed}
-        options={{title: title('Home Feed Preferences')}}
+        options={{title: title('Home Feed Preferences'), requireAuth: true}}
       />
       <Stack.Screen
         name="PreferencesThreads"
         getComponent={() => PreferencesThreads}
-        options={{title: title('Threads Preferences')}}
+        options={{title: title('Threads Preferences'), requireAuth: true}}
       />
     </>
   )
@@ -339,6 +340,7 @@ function NotificationsTabNavigator() {
       <NotificationsTab.Screen
         name="Notifications"
         getComponent={() => NotificationsScreen}
+        options={{requireAuth: true}}
       />
       {commonScreens(NotificationsTab as typeof HomeTab)}
     </NotificationsTab.Navigator>
@@ -357,8 +359,8 @@ function MyProfileTabNavigator() {
         contentStyle,
       }}>
       <MyProfileTab.Screen
-        name="MyProfile"
         // @ts-ignore // TODO: fix this broken type in ProfileScreen
+        name="MyProfile"
         getComponent={() => ProfileScreen}
         initialParams={{
           name: 'me',
@@ -405,7 +407,7 @@ const FlatNavigator = () => {
       <Flat.Screen
         name="Notifications"
         getComponent={() => NotificationsScreen}
-        options={{title: title('Notifications')}}
+        options={{title: title('Notifications'), requireAuth: true}}
       />
       {commonScreens(Flat as typeof HomeTab, numUnread)}
     </Flat.Navigator>
diff --git a/src/state/shell/index.tsx b/src/state/shell/index.tsx
index 897a66020..53f05055c 100644
--- a/src/state/shell/index.tsx
+++ b/src/state/shell/index.tsx
@@ -7,7 +7,6 @@ import {Provider as ColorModeProvider} from './color-mode'
 import {Provider as OnboardingProvider} from './onboarding'
 import {Provider as ComposerProvider} from './composer'
 import {Provider as TickEveryMinuteProvider} from './tick-every-minute'
-import {Provider as LoggedOutViewProvider} from './logged-out'
 
 export {useIsDrawerOpen, useSetDrawerOpen} from './drawer-open'
 export {
@@ -23,23 +22,19 @@ export {useTickEveryMinute} from './tick-every-minute'
 export function Provider({children}: React.PropsWithChildren<{}>) {
   return (
     <ShellLayoutProvder>
-      <LoggedOutViewProvider>
-        <DrawerOpenProvider>
-          <DrawerSwipableProvider>
-            <MinimalModeProvider>
-              <ColorModeProvider>
-                <OnboardingProvider>
-                  <ComposerProvider>
-                    <TickEveryMinuteProvider>
-                      {children}
-                    </TickEveryMinuteProvider>
-                  </ComposerProvider>
-                </OnboardingProvider>
-              </ColorModeProvider>
-            </MinimalModeProvider>
-          </DrawerSwipableProvider>
-        </DrawerOpenProvider>
-      </LoggedOutViewProvider>
+      <DrawerOpenProvider>
+        <DrawerSwipableProvider>
+          <MinimalModeProvider>
+            <ColorModeProvider>
+              <OnboardingProvider>
+                <ComposerProvider>
+                  <TickEveryMinuteProvider>{children}</TickEveryMinuteProvider>
+                </ComposerProvider>
+              </OnboardingProvider>
+            </ColorModeProvider>
+          </MinimalModeProvider>
+        </DrawerSwipableProvider>
+      </DrawerOpenProvider>
     </ShellLayoutProvder>
   )
 }
diff --git a/src/view/com/auth/withAuthRequired.tsx b/src/view/com/auth/withAuthRequired.tsx
deleted file mode 100644
index 7a9138545..000000000
--- a/src/view/com/auth/withAuthRequired.tsx
+++ /dev/null
@@ -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',
-  },
-})
diff --git a/src/view/screens/AppPasswords.tsx b/src/view/screens/AppPasswords.tsx
index bc77a48cd..154035f22 100644
--- a/src/view/screens/AppPasswords.tsx
+++ b/src/view/screens/AppPasswords.tsx
@@ -12,7 +12,6 @@ import {Button} from '../com/util/forms/Button'
 import * as Toast from '../com/util/Toast'
 import {usePalette} from 'lib/hooks/usePalette'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {NativeStackScreenProps} from '@react-navigation/native-stack'
 import {CommonNavigatorParams} from 'lib/routes/types'
 import {useAnalytics} from 'lib/analytics/analytics'
@@ -32,125 +31,111 @@ import {ErrorScreen} from '../com/util/error/ErrorScreen'
 import {cleanError} from '#/lib/strings/errors'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'AppPasswords'>
-export const AppPasswords = withAuthRequired(
-  function AppPasswordsImpl({}: Props) {
-    const pal = usePalette('default')
-    const setMinimalShellMode = useSetMinimalShellMode()
-    const {screen} = useAnalytics()
-    const {isTabletOrDesktop} = useWebMediaQueries()
-    const {openModal} = useModalControls()
-    const {data: appPasswords, error} = useAppPasswordsQuery()
+export function AppPasswords({}: Props) {
+  const pal = usePalette('default')
+  const setMinimalShellMode = useSetMinimalShellMode()
+  const {screen} = useAnalytics()
+  const {isTabletOrDesktop} = useWebMediaQueries()
+  const {openModal} = useModalControls()
+  const {data: appPasswords, error} = useAppPasswordsQuery()
 
-    useFocusEffect(
-      React.useCallback(() => {
-        screen('AppPasswords')
-        setMinimalShellMode(false)
-      }, [screen, setMinimalShellMode]),
-    )
+  useFocusEffect(
+    React.useCallback(() => {
+      screen('AppPasswords')
+      setMinimalShellMode(false)
+    }, [screen, setMinimalShellMode]),
+  )
 
-    const onAdd = React.useCallback(async () => {
-      openModal({name: 'add-app-password'})
-    }, [openModal])
+  const onAdd = React.useCallback(async () => {
+    openModal({name: 'add-app-password'})
+  }, [openModal])
 
-    if (error) {
-      return (
-        <CenteredView
+  if (error) {
+    return (
+      <CenteredView
+        style={[
+          styles.container,
+          isTabletOrDesktop && styles.containerDesktop,
+          pal.view,
+          pal.border,
+        ]}
+        testID="appPasswordsScreen">
+        <ErrorScreen
+          title="Oops!"
+          message="There was an issue with fetching your app passwords"
+          details={cleanError(error)}
+        />
+      </CenteredView>
+    )
+  }
+
+  // no app passwords (empty) state
+  if (appPasswords?.length === 0) {
+    return (
+      <CenteredView
+        style={[
+          styles.container,
+          isTabletOrDesktop && styles.containerDesktop,
+          pal.view,
+          pal.border,
+        ]}
+        testID="appPasswordsScreen">
+        <AppPasswordsHeader />
+        <View style={[styles.empty, pal.viewLight]}>
+          <Text type="lg" style={[pal.text, styles.emptyText]}>
+            <Trans>
+              You have not created any app passwords yet. You can create one by
+              pressing the button below.
+            </Trans>
+          </Text>
+        </View>
+        {!isTabletOrDesktop && <View style={styles.flex1} />}
+        <View
           style={[
-            styles.container,
-            isTabletOrDesktop && styles.containerDesktop,
-            pal.view,
-            pal.border,
-          ]}
-          testID="appPasswordsScreen">
-          <ErrorScreen
-            title="Oops!"
-            message="There was an issue with fetching your app passwords"
-            details={cleanError(error)}
+            styles.btnContainer,
+            isTabletOrDesktop && styles.btnContainerDesktop,
+          ]}>
+          <Button
+            testID="appPasswordBtn"
+            type="primary"
+            label="Add App Password"
+            style={styles.btn}
+            labelStyle={styles.btnLabel}
+            onPress={onAdd}
           />
-        </CenteredView>
-      )
-    }
+        </View>
+      </CenteredView>
+    )
+  }
 
-    // no app passwords (empty) state
-    if (appPasswords?.length === 0) {
-      return (
-        <CenteredView
+  if (appPasswords?.length) {
+    // has app passwords
+    return (
+      <CenteredView
+        style={[
+          styles.container,
+          isTabletOrDesktop && styles.containerDesktop,
+          pal.view,
+          pal.border,
+        ]}
+        testID="appPasswordsScreen">
+        <AppPasswordsHeader />
+        <ScrollView
           style={[
-            styles.container,
-            isTabletOrDesktop && styles.containerDesktop,
-            pal.view,
+            styles.scrollContainer,
             pal.border,
-          ]}
-          testID="appPasswordsScreen">
-          <AppPasswordsHeader />
-          <View style={[styles.empty, pal.viewLight]}>
-            <Text type="lg" style={[pal.text, styles.emptyText]}>
-              <Trans>
-                You have not created any app passwords yet. You can create one
-                by pressing the button below.
-              </Trans>
-            </Text>
-          </View>
-          {!isTabletOrDesktop && <View style={styles.flex1} />}
-          <View
-            style={[
-              styles.btnContainer,
-              isTabletOrDesktop && styles.btnContainerDesktop,
-            ]}>
-            <Button
-              testID="appPasswordBtn"
-              type="primary"
-              label="Add App Password"
-              style={styles.btn}
-              labelStyle={styles.btnLabel}
-              onPress={onAdd}
+            !isTabletOrDesktop && styles.flex1,
+          ]}>
+          {appPasswords.map((password, i) => (
+            <AppPassword
+              key={password.name}
+              testID={`appPassword-${i}`}
+              name={password.name}
+              createdAt={password.createdAt}
             />
-          </View>
-        </CenteredView>
-      )
-    }
-
-    if (appPasswords?.length) {
-      // has app passwords
-      return (
-        <CenteredView
-          style={[
-            styles.container,
-            isTabletOrDesktop && styles.containerDesktop,
-            pal.view,
-            pal.border,
-          ]}
-          testID="appPasswordsScreen">
-          <AppPasswordsHeader />
-          <ScrollView
-            style={[
-              styles.scrollContainer,
-              pal.border,
-              !isTabletOrDesktop && styles.flex1,
-            ]}>
-            {appPasswords.map((password, i) => (
-              <AppPassword
-                key={password.name}
-                testID={`appPassword-${i}`}
-                name={password.name}
-                createdAt={password.createdAt}
-              />
-            ))}
-            {isTabletOrDesktop && (
-              <View style={[styles.btnContainer, styles.btnContainerDesktop]}>
-                <Button
-                  testID="appPasswordBtn"
-                  type="primary"
-                  label="Add App Password"
-                  style={styles.btn}
-                  labelStyle={styles.btnLabel}
-                  onPress={onAdd}
-                />
-              </View>
-            )}
-          </ScrollView>
-          {!isTabletOrDesktop && (
-            <View style={styles.btnContainer}>
+          ))}
+          {isTabletOrDesktop && (
+            <View style={[styles.btnContainer, styles.btnContainerDesktop]}>
               <Button
                 testID="appPasswordBtn"
                 type="primary"
@@ -161,24 +146,36 @@ export const AppPasswords = withAuthRequired(
               />
             </View>
           )}
-        </CenteredView>
-      )
-    }
-
-    return (
-      <CenteredView
-        style={[
-          styles.container,
-          isTabletOrDesktop && styles.containerDesktop,
-          pal.view,
-          pal.border,
-        ]}
-        testID="appPasswordsScreen">
-        <ActivityIndicator />
+        </ScrollView>
+        {!isTabletOrDesktop && (
+          <View style={styles.btnContainer}>
+            <Button
+              testID="appPasswordBtn"
+              type="primary"
+              label="Add App Password"
+              style={styles.btn}
+              labelStyle={styles.btnLabel}
+              onPress={onAdd}
+            />
+          </View>
+        )}
       </CenteredView>
     )
-  },
-)
+  }
+
+  return (
+    <CenteredView
+      style={[
+        styles.container,
+        isTabletOrDesktop && styles.containerDesktop,
+        pal.view,
+        pal.border,
+      ]}
+      testID="appPasswordsScreen">
+      <ActivityIndicator />
+    </CenteredView>
+  )
+}
 
 function AppPasswordsHeader() {
   const {isTabletOrDesktop} = useWebMediaQueries()
diff --git a/src/view/screens/Feeds.tsx b/src/view/screens/Feeds.tsx
index f8fc0db17..ced8592c5 100644
--- a/src/view/screens/Feeds.tsx
+++ b/src/view/screens/Feeds.tsx
@@ -2,7 +2,6 @@ import React from 'react'
 import {ActivityIndicator, StyleSheet, View, RefreshControl} from 'react-native'
 import {FontAwesomeIcon} 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 {FAB} from 'view/com/util/fab/FAB'
 import {Link} from 'view/com/util/Link'
@@ -88,437 +87,432 @@ type FlatlistSlice =
       key: string
     }
 
-export const FeedsScreen = withAuthRequired(
-  function FeedsScreenImpl(_props: Props) {
-    const pal = usePalette('default')
-    const {openComposer} = useComposerControls()
-    const {isMobile, isTabletOrDesktop} = useWebMediaQueries()
-    const [query, setQuery] = React.useState('')
-    const [isPTR, setIsPTR] = React.useState(false)
-    const {
-      data: preferences,
-      isLoading: isPreferencesLoading,
-      error: preferencesError,
-    } = usePreferencesQuery()
-    const {
-      data: popularFeeds,
-      isFetching: isPopularFeedsFetching,
-      error: popularFeedsError,
-      refetch: refetchPopularFeeds,
-      fetchNextPage: fetchNextPopularFeedsPage,
-      isFetchingNextPage: isPopularFeedsFetchingNextPage,
-      hasNextPage: hasNextPopularFeedsPage,
-    } = useGetPopularFeedsQuery()
-    const {_} = useLingui()
-    const setMinimalShellMode = useSetMinimalShellMode()
-    const {
-      data: searchResults,
-      mutate: search,
-      reset: resetSearch,
-      isPending: isSearchPending,
-      error: searchError,
-    } = useSearchPopularFeedsMutation()
-    const {hasSession} = useSession()
+export function FeedsScreen(_props: Props) {
+  const pal = usePalette('default')
+  const {openComposer} = useComposerControls()
+  const {isMobile, isTabletOrDesktop} = useWebMediaQueries()
+  const [query, setQuery] = React.useState('')
+  const [isPTR, setIsPTR] = React.useState(false)
+  const {
+    data: preferences,
+    isLoading: isPreferencesLoading,
+    error: preferencesError,
+  } = usePreferencesQuery()
+  const {
+    data: popularFeeds,
+    isFetching: isPopularFeedsFetching,
+    error: popularFeedsError,
+    refetch: refetchPopularFeeds,
+    fetchNextPage: fetchNextPopularFeedsPage,
+    isFetchingNextPage: isPopularFeedsFetchingNextPage,
+    hasNextPage: hasNextPopularFeedsPage,
+  } = useGetPopularFeedsQuery()
+  const {_} = useLingui()
+  const setMinimalShellMode = useSetMinimalShellMode()
+  const {
+    data: searchResults,
+    mutate: search,
+    reset: resetSearch,
+    isPending: isSearchPending,
+    error: searchError,
+  } = useSearchPopularFeedsMutation()
+  const {hasSession} = useSession()
 
-    /**
-     * A search query is present. We may not have search results yet.
-     */
-    const isUserSearching = query.length > 1
-    const debouncedSearch = React.useMemo(
-      () => debounce(q => search(q), 500), // debounce for 500ms
-      [search],
-    )
-    const onPressCompose = React.useCallback(() => {
-      openComposer({})
-    }, [openComposer])
-    const onChangeQuery = React.useCallback(
-      (text: string) => {
-        setQuery(text)
-        if (text.length > 1) {
-          debouncedSearch(text)
-        } else {
-          refetchPopularFeeds()
-          resetSearch()
-        }
-      },
-      [setQuery, refetchPopularFeeds, debouncedSearch, resetSearch],
+  /**
+   * A search query is present. We may not have search results yet.
+   */
+  const isUserSearching = query.length > 1
+  const debouncedSearch = React.useMemo(
+    () => debounce(q => search(q), 500), // debounce for 500ms
+    [search],
+  )
+  const onPressCompose = React.useCallback(() => {
+    openComposer({})
+  }, [openComposer])
+  const onChangeQuery = React.useCallback(
+    (text: string) => {
+      setQuery(text)
+      if (text.length > 1) {
+        debouncedSearch(text)
+      } else {
+        refetchPopularFeeds()
+        resetSearch()
+      }
+    },
+    [setQuery, refetchPopularFeeds, debouncedSearch, resetSearch],
+  )
+  const onPressCancelSearch = React.useCallback(() => {
+    setQuery('')
+    refetchPopularFeeds()
+    resetSearch()
+  }, [refetchPopularFeeds, setQuery, resetSearch])
+  const onSubmitQuery = React.useCallback(() => {
+    debouncedSearch(query)
+  }, [query, debouncedSearch])
+  const onPullToRefresh = React.useCallback(async () => {
+    setIsPTR(true)
+    await refetchPopularFeeds()
+    setIsPTR(false)
+  }, [setIsPTR, refetchPopularFeeds])
+  const onEndReached = React.useCallback(() => {
+    if (
+      isPopularFeedsFetching ||
+      isUserSearching ||
+      !hasNextPopularFeedsPage ||
+      popularFeedsError
     )
-    const onPressCancelSearch = React.useCallback(() => {
-      setQuery('')
-      refetchPopularFeeds()
-      resetSearch()
-    }, [refetchPopularFeeds, setQuery, resetSearch])
-    const onSubmitQuery = React.useCallback(() => {
-      debouncedSearch(query)
-    }, [query, debouncedSearch])
-    const onPullToRefresh = React.useCallback(async () => {
-      setIsPTR(true)
-      await refetchPopularFeeds()
-      setIsPTR(false)
-    }, [setIsPTR, refetchPopularFeeds])
-    const onEndReached = React.useCallback(() => {
-      if (
-        isPopularFeedsFetching ||
-        isUserSearching ||
-        !hasNextPopularFeedsPage ||
-        popularFeedsError
-      )
-        return
-      fetchNextPopularFeedsPage()
-    }, [
-      isPopularFeedsFetching,
-      isUserSearching,
-      popularFeedsError,
-      hasNextPopularFeedsPage,
-      fetchNextPopularFeedsPage,
-    ])
+      return
+    fetchNextPopularFeedsPage()
+  }, [
+    isPopularFeedsFetching,
+    isUserSearching,
+    popularFeedsError,
+    hasNextPopularFeedsPage,
+    fetchNextPopularFeedsPage,
+  ])
 
-    useFocusEffect(
-      React.useCallback(() => {
-        setMinimalShellMode(false)
-      }, [setMinimalShellMode]),
-    )
+  useFocusEffect(
+    React.useCallback(() => {
+      setMinimalShellMode(false)
+    }, [setMinimalShellMode]),
+  )
 
-    const items = React.useMemo(() => {
-      let slices: FlatlistSlice[] = []
+  const items = React.useMemo(() => {
+    let slices: FlatlistSlice[] = []
 
-      if (hasSession) {
+    if (hasSession) {
+      slices.push({
+        key: 'savedFeedsHeader',
+        type: 'savedFeedsHeader',
+      })
+
+      if (preferencesError) {
         slices.push({
-          key: 'savedFeedsHeader',
-          type: 'savedFeedsHeader',
+          key: 'savedFeedsError',
+          type: 'error',
+          error: cleanError(preferencesError.toString()),
         })
-
-        if (preferencesError) {
+      } else {
+        if (isPreferencesLoading || !preferences?.feeds?.saved) {
           slices.push({
-            key: 'savedFeedsError',
-            type: 'error',
-            error: cleanError(preferencesError.toString()),
+            key: 'savedFeedsLoading',
+            type: 'savedFeedsLoading',
+            // pendingItems: this.rootStore.preferences.savedFeeds.length || 3,
           })
         } else {
-          if (isPreferencesLoading || !preferences?.feeds?.saved) {
+          if (preferences?.feeds?.saved.length === 0) {
             slices.push({
-              key: 'savedFeedsLoading',
-              type: 'savedFeedsLoading',
-              // pendingItems: this.rootStore.preferences.savedFeeds.length || 3,
+              key: 'savedFeedNoResults',
+              type: 'savedFeedNoResults',
             })
           } else {
-            if (preferences?.feeds?.saved.length === 0) {
-              slices.push({
-                key: 'savedFeedNoResults',
-                type: 'savedFeedNoResults',
-              })
-            } else {
-              const {saved, pinned} = preferences.feeds
+            const {saved, pinned} = preferences.feeds
 
-              slices = slices.concat(
-                pinned.map(uri => ({
+            slices = slices.concat(
+              pinned.map(uri => ({
+                key: `savedFeed:${uri}`,
+                type: 'savedFeed',
+                feedUri: uri,
+              })),
+            )
+
+            slices = slices.concat(
+              saved
+                .filter(uri => !pinned.includes(uri))
+                .map(uri => ({
                   key: `savedFeed:${uri}`,
                   type: 'savedFeed',
                   feedUri: uri,
                 })),
-              )
-
-              slices = slices.concat(
-                saved
-                  .filter(uri => !pinned.includes(uri))
-                  .map(uri => ({
-                    key: `savedFeed:${uri}`,
-                    type: 'savedFeed',
-                    feedUri: uri,
-                  })),
-              )
-            }
+            )
           }
         }
       }
+    }
+
+    slices.push({
+      key: 'popularFeedsHeader',
+      type: 'popularFeedsHeader',
+    })
 
+    if (popularFeedsError || searchError) {
       slices.push({
-        key: 'popularFeedsHeader',
-        type: 'popularFeedsHeader',
+        key: 'popularFeedsError',
+        type: 'error',
+        error: cleanError(
+          popularFeedsError?.toString() ?? searchError?.toString() ?? '',
+        ),
       })
-
-      if (popularFeedsError || searchError) {
-        slices.push({
-          key: 'popularFeedsError',
-          type: 'error',
-          error: cleanError(
-            popularFeedsError?.toString() ?? searchError?.toString() ?? '',
-          ),
-        })
-      } else {
-        if (isUserSearching) {
-          if (isSearchPending || !searchResults) {
+    } else {
+      if (isUserSearching) {
+        if (isSearchPending || !searchResults) {
+          slices.push({
+            key: 'popularFeedsLoading',
+            type: 'popularFeedsLoading',
+          })
+        } else {
+          if (!searchResults || searchResults?.length === 0) {
             slices.push({
-              key: 'popularFeedsLoading',
-              type: 'popularFeedsLoading',
+              key: 'popularFeedsNoResults',
+              type: 'popularFeedsNoResults',
             })
           } else {
-            if (!searchResults || searchResults?.length === 0) {
-              slices.push({
-                key: 'popularFeedsNoResults',
-                type: 'popularFeedsNoResults',
-              })
-            } else {
-              slices = slices.concat(
-                searchResults.map(feed => ({
-                  key: `popularFeed:${feed.uri}`,
-                  type: 'popularFeed',
-                  feedUri: feed.uri,
-                })),
-              )
-            }
+            slices = slices.concat(
+              searchResults.map(feed => ({
+                key: `popularFeed:${feed.uri}`,
+                type: 'popularFeed',
+                feedUri: feed.uri,
+              })),
+            )
           }
+        }
+      } else {
+        if (isPopularFeedsFetching && !popularFeeds?.pages) {
+          slices.push({
+            key: 'popularFeedsLoading',
+            type: 'popularFeedsLoading',
+          })
         } else {
-          if (isPopularFeedsFetching && !popularFeeds?.pages) {
+          if (
+            !popularFeeds?.pages ||
+            popularFeeds?.pages[0]?.feeds?.length === 0
+          ) {
             slices.push({
-              key: 'popularFeedsLoading',
-              type: 'popularFeedsLoading',
+              key: 'popularFeedsNoResults',
+              type: 'popularFeedsNoResults',
             })
           } else {
-            if (
-              !popularFeeds?.pages ||
-              popularFeeds?.pages[0]?.feeds?.length === 0
-            ) {
+            for (const page of popularFeeds.pages || []) {
+              slices = slices.concat(
+                page.feeds
+                  .filter(feed => !preferences?.feeds?.saved.includes(feed.uri))
+                  .map(feed => ({
+                    key: `popularFeed:${feed.uri}`,
+                    type: 'popularFeed',
+                    feedUri: feed.uri,
+                  })),
+              )
+            }
+
+            if (isPopularFeedsFetchingNextPage) {
               slices.push({
-                key: 'popularFeedsNoResults',
-                type: 'popularFeedsNoResults',
+                key: 'popularFeedsLoadingMore',
+                type: 'popularFeedsLoadingMore',
               })
-            } else {
-              for (const page of popularFeeds.pages || []) {
-                slices = slices.concat(
-                  page.feeds
-                    .filter(
-                      feed => !preferences?.feeds?.saved.includes(feed.uri),
-                    )
-                    .map(feed => ({
-                      key: `popularFeed:${feed.uri}`,
-                      type: 'popularFeed',
-                      feedUri: feed.uri,
-                    })),
-                )
-              }
-
-              if (isPopularFeedsFetchingNextPage) {
-                slices.push({
-                  key: 'popularFeedsLoadingMore',
-                  type: 'popularFeedsLoadingMore',
-                })
-              }
             }
           }
         }
       }
+    }
 
-      return slices
-    }, [
-      hasSession,
-      preferences,
-      isPreferencesLoading,
-      preferencesError,
-      popularFeeds,
-      isPopularFeedsFetching,
-      popularFeedsError,
-      isPopularFeedsFetchingNextPage,
-      searchResults,
-      isSearchPending,
-      searchError,
-      isUserSearching,
-    ])
+    return slices
+  }, [
+    hasSession,
+    preferences,
+    isPreferencesLoading,
+    preferencesError,
+    popularFeeds,
+    isPopularFeedsFetching,
+    popularFeedsError,
+    isPopularFeedsFetchingNextPage,
+    searchResults,
+    isSearchPending,
+    searchError,
+    isUserSearching,
+  ])
 
-    const renderHeaderBtn = React.useCallback(() => {
-      return (
-        <Link
-          href="/settings/saved-feeds"
-          hitSlop={10}
-          accessibilityRole="button"
-          accessibilityLabel={_(msg`Edit Saved Feeds`)}
-          accessibilityHint="Opens screen to edit Saved Feeds">
-          <CogIcon size={22} strokeWidth={2} style={pal.textLight} />
-        </Link>
-      )
-    }, [pal, _])
+  const renderHeaderBtn = React.useCallback(() => {
+    return (
+      <Link
+        href="/settings/saved-feeds"
+        hitSlop={10}
+        accessibilityRole="button"
+        accessibilityLabel={_(msg`Edit Saved Feeds`)}
+        accessibilityHint="Opens screen to edit Saved Feeds">
+        <CogIcon size={22} strokeWidth={2} style={pal.textLight} />
+      </Link>
+    )
+  }, [pal, _])
 
-    const renderItem = React.useCallback(
-      ({item}: {item: FlatlistSlice}) => {
-        if (item.type === 'error') {
-          return <ErrorMessage message={item.error} />
-        } else if (
-          item.type === 'popularFeedsLoadingMore' ||
-          item.type === 'savedFeedsLoading'
-        ) {
-          return (
-            <View style={s.p10}>
-              <ActivityIndicator />
-            </View>
-          )
-        } else if (item.type === 'savedFeedsHeader') {
-          if (!isMobile) {
-            return (
-              <View
-                style={[
-                  pal.view,
-                  styles.header,
-                  pal.border,
-                  {
-                    borderBottomWidth: 1,
-                  },
-                ]}>
-                <Text type="title-lg" style={[pal.text, s.bold]}>
-                  <Trans>My Feeds</Trans>
-                </Text>
-                <Link
-                  href="/settings/saved-feeds"
-                  accessibilityLabel={_(msg`Edit My Feeds`)}
-                  accessibilityHint="">
-                  <CogIcon strokeWidth={1.5} style={pal.icon} size={28} />
-                </Link>
-              </View>
-            )
-          }
-          return <View />
-        } else if (item.type === 'savedFeedNoResults') {
+  const renderItem = React.useCallback(
+    ({item}: {item: FlatlistSlice}) => {
+      if (item.type === 'error') {
+        return <ErrorMessage message={item.error} />
+      } else if (
+        item.type === 'popularFeedsLoadingMore' ||
+        item.type === 'savedFeedsLoading'
+      ) {
+        return (
+          <View style={s.p10}>
+            <ActivityIndicator />
+          </View>
+        )
+      } else if (item.type === 'savedFeedsHeader') {
+        if (!isMobile) {
           return (
             <View
-              style={{
-                paddingHorizontal: 16,
-                paddingTop: 10,
-              }}>
-              <Text type="lg" style={pal.textLight}>
-                <Trans>You don't have any saved feeds!</Trans>
+              style={[
+                pal.view,
+                styles.header,
+                pal.border,
+                {
+                  borderBottomWidth: 1,
+                },
+              ]}>
+              <Text type="title-lg" style={[pal.text, s.bold]}>
+                <Trans>My Feeds</Trans>
               </Text>
+              <Link
+                href="/settings/saved-feeds"
+                accessibilityLabel={_(msg`Edit My Feeds`)}
+                accessibilityHint="">
+                <CogIcon strokeWidth={1.5} style={pal.icon} size={28} />
+              </Link>
             </View>
           )
-        } else if (item.type === 'savedFeed') {
-          return <SavedFeed feedUri={item.feedUri} />
-        } else if (item.type === 'popularFeedsHeader') {
-          return (
-            <>
-              <View
-                style={[
-                  pal.view,
-                  styles.header,
-                  {
-                    // This is first in the flatlist without a session -esb
-                    marginTop: hasSession ? 16 : 0,
-                    paddingLeft: isMobile ? 12 : undefined,
-                    paddingRight: 10,
-                    paddingBottom: isMobile ? 6 : undefined,
-                  },
-                ]}>
-                <Text type="title-lg" style={[pal.text, s.bold]}>
-                  <Trans>Discover new feeds</Trans>
-                </Text>
-
-                {!isMobile && (
-                  <SearchInput
-                    query={query}
-                    onChangeQuery={onChangeQuery}
-                    onPressCancelSearch={onPressCancelSearch}
-                    onSubmitQuery={onSubmitQuery}
-                    style={{flex: 1, maxWidth: 250}}
-                  />
-                )}
-              </View>
-
-              {isMobile && (
-                <View style={{paddingHorizontal: 8, paddingBottom: 10}}>
-                  <SearchInput
-                    query={query}
-                    onChangeQuery={onChangeQuery}
-                    onPressCancelSearch={onPressCancelSearch}
-                    onSubmitQuery={onSubmitQuery}
-                  />
-                </View>
-              )}
-            </>
-          )
-        } else if (item.type === 'popularFeedsLoading') {
-          return <FeedFeedLoadingPlaceholder />
-        } else if (item.type === 'popularFeed') {
-          return (
-            <FeedSourceCard
-              feedUri={item.feedUri}
-              showSaveBtn={hasSession}
-              showDescription
-              showLikes
-            />
-          )
-        } else if (item.type === 'popularFeedsNoResults') {
-          return (
+        }
+        return <View />
+      } else if (item.type === 'savedFeedNoResults') {
+        return (
+          <View
+            style={{
+              paddingHorizontal: 16,
+              paddingTop: 10,
+            }}>
+            <Text type="lg" style={pal.textLight}>
+              <Trans>You don't have any saved feeds!</Trans>
+            </Text>
+          </View>
+        )
+      } else if (item.type === 'savedFeed') {
+        return <SavedFeed feedUri={item.feedUri} />
+      } else if (item.type === 'popularFeedsHeader') {
+        return (
+          <>
             <View
-              style={{
-                paddingHorizontal: 16,
-                paddingTop: 10,
-                paddingBottom: '150%',
-              }}>
-              <Text type="lg" style={pal.textLight}>
-                <Trans>No results found for "{query}"</Trans>
+              style={[
+                pal.view,
+                styles.header,
+                {
+                  // This is first in the flatlist without a session -esb
+                  marginTop: hasSession ? 16 : 0,
+                  paddingLeft: isMobile ? 12 : undefined,
+                  paddingRight: 10,
+                  paddingBottom: isMobile ? 6 : undefined,
+                },
+              ]}>
+              <Text type="title-lg" style={[pal.text, s.bold]}>
+                <Trans>Discover new feeds</Trans>
               </Text>
+
+              {!isMobile && (
+                <SearchInput
+                  query={query}
+                  onChangeQuery={onChangeQuery}
+                  onPressCancelSearch={onPressCancelSearch}
+                  onSubmitQuery={onSubmitQuery}
+                  style={{flex: 1, maxWidth: 250}}
+                />
+              )}
             </View>
-          )
-        }
-        return null
-      },
-      [
-        _,
-        hasSession,
-        isMobile,
-        pal,
-        query,
-        onChangeQuery,
-        onPressCancelSearch,
-        onSubmitQuery,
-      ],
-    )
 
-    return (
-      <View style={[pal.view, styles.container]}>
-        {isMobile && (
-          <ViewHeader
-            title={_(msg`Feeds`)}
-            canGoBack={false}
-            renderButton={renderHeaderBtn}
-            showBorder
+            {isMobile && (
+              <View style={{paddingHorizontal: 8, paddingBottom: 10}}>
+                <SearchInput
+                  query={query}
+                  onChangeQuery={onChangeQuery}
+                  onPressCancelSearch={onPressCancelSearch}
+                  onSubmitQuery={onSubmitQuery}
+                />
+              </View>
+            )}
+          </>
+        )
+      } else if (item.type === 'popularFeedsLoading') {
+        return <FeedFeedLoadingPlaceholder />
+      } else if (item.type === 'popularFeed') {
+        return (
+          <FeedSourceCard
+            feedUri={item.feedUri}
+            showSaveBtn={hasSession}
+            showDescription
+            showLikes
           />
-        )}
-
-        {preferences ? <View /> : <ActivityIndicator />}
+        )
+      } else if (item.type === 'popularFeedsNoResults') {
+        return (
+          <View
+            style={{
+              paddingHorizontal: 16,
+              paddingTop: 10,
+              paddingBottom: '150%',
+            }}>
+            <Text type="lg" style={pal.textLight}>
+              <Trans>No results found for "{query}"</Trans>
+            </Text>
+          </View>
+        )
+      }
+      return null
+    },
+    [
+      _,
+      hasSession,
+      isMobile,
+      pal,
+      query,
+      onChangeQuery,
+      onPressCancelSearch,
+      onSubmitQuery,
+    ],
+  )
 
-        <FlatList
-          style={[!isTabletOrDesktop && s.flex1, styles.list]}
-          data={items}
-          keyExtractor={item => item.key}
-          contentContainerStyle={styles.contentContainer}
-          renderItem={renderItem}
-          refreshControl={
-            <RefreshControl
-              refreshing={isPTR}
-              onRefresh={isUserSearching ? undefined : onPullToRefresh}
-              tintColor={pal.colors.text}
-              titleColor={pal.colors.text}
-            />
-          }
-          initialNumToRender={10}
-          onEndReached={onEndReached}
-          // @ts-ignore our .web version only -prf
-          desktopFixedHeight
+  return (
+    <View style={[pal.view, styles.container]}>
+      {isMobile && (
+        <ViewHeader
+          title={_(msg`Feeds`)}
+          canGoBack={false}
+          renderButton={renderHeaderBtn}
+          showBorder
         />
+      )}
 
-        {hasSession && (
-          <FAB
-            testID="composeFAB"
-            onPress={onPressCompose}
-            icon={<ComposeIcon2 strokeWidth={1.5} size={29} style={s.white} />}
-            accessibilityRole="button"
-            accessibilityLabel={_(msg`New post`)}
-            accessibilityHint=""
+      {preferences ? <View /> : <ActivityIndicator />}
+
+      <FlatList
+        style={[!isTabletOrDesktop && s.flex1, styles.list]}
+        data={items}
+        keyExtractor={item => item.key}
+        contentContainerStyle={styles.contentContainer}
+        renderItem={renderItem}
+        refreshControl={
+          <RefreshControl
+            refreshing={isPTR}
+            onRefresh={isUserSearching ? undefined : onPullToRefresh}
+            tintColor={pal.colors.text}
+            titleColor={pal.colors.text}
           />
-        )}
-      </View>
-    )
-  },
-  {isPublic: true},
-)
+        }
+        initialNumToRender={10}
+        onEndReached={onEndReached}
+        // @ts-ignore our .web version only -prf
+        desktopFixedHeight
+      />
+
+      {hasSession && (
+        <FAB
+          testID="composeFAB"
+          onPress={onPressCompose}
+          icon={<ComposeIcon2 strokeWidth={1.5} size={29} style={s.white} />}
+          accessibilityRole="button"
+          accessibilityLabel={_(msg`New post`)}
+          accessibilityHint=""
+        />
+      )}
+    </View>
+  )
+}
 
 function SavedFeed({feedUri}: {feedUri: string}) {
   const pal = usePalette('default')
diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx
index 8df945cd2..015c436f4 100644
--- a/src/view/screens/Home.tsx
+++ b/src/view/screens/Home.tsx
@@ -3,7 +3,6 @@ import {View, ActivityIndicator, StyleSheet} from 'react-native'
 import {useFocusEffect} from '@react-navigation/native'
 import {NativeStackScreenProps, HomeTabNavigatorParams} from 'lib/routes/types'
 import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {FollowingEmptyState} from 'view/com/posts/FollowingEmptyState'
 import {FollowingEndOfFeed} from 'view/com/posts/FollowingEndOfFeed'
 import {CustomFeedEmptyState} from 'view/com/posts/CustomFeedEmptyState'
@@ -17,29 +16,24 @@ import {emitSoftReset} from '#/state/events'
 import {useSession} from '#/state/session'
 
 type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'>
-export const HomeScreen = withAuthRequired(
-  function HomeScreenImpl(props: Props) {
-    const {hasSession} = useSession()
-    const {data: preferences} = usePreferencesQuery()
-
-    if (!hasSession) {
-      return <HomeScreenPublic />
-    }
-
-    if (preferences) {
-      return <HomeScreenReady {...props} preferences={preferences} />
-    } else {
-      return (
-        <View style={styles.loading}>
-          <ActivityIndicator size="large" />
-        </View>
-      )
-    }
-  },
-  {
-    isPublic: true,
-  },
-)
+export function HomeScreen(props: Props) {
+  const {hasSession} = useSession()
+  const {data: preferences} = usePreferencesQuery()
+
+  if (!hasSession) {
+    return <HomeScreenPublic />
+  }
+
+  if (preferences) {
+    return <HomeScreenReady {...props} preferences={preferences} />
+  } else {
+    return (
+      <View style={styles.loading}>
+        <ActivityIndicator size="large" />
+      </View>
+    )
+  }
+}
 
 function HomeScreenPublic() {
   const setMinimalShellMode = useSetMinimalShellMode()
diff --git a/src/view/screens/Lists.tsx b/src/view/screens/Lists.tsx
index c97be4a02..d28db7c6c 100644
--- a/src/view/screens/Lists.tsx
+++ b/src/view/screens/Lists.tsx
@@ -4,7 +4,6 @@ import {useFocusEffect, useNavigation} from '@react-navigation/native'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
 import {AtUri} from '@atproto/api'
 import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {MyLists} from '#/view/com/lists/MyLists'
 import {Text} from 'view/com/util/text/Text'
 import {Button} from 'view/com/util/forms/Button'
@@ -18,70 +17,68 @@ import {useModalControls} from '#/state/modals'
 import {Trans} from '@lingui/macro'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'Lists'>
-export const ListsScreen = withAuthRequired(
-  function ListsScreenImpl({}: Props) {
-    const pal = usePalette('default')
-    const setMinimalShellMode = useSetMinimalShellMode()
-    const {isMobile} = useWebMediaQueries()
-    const navigation = useNavigation<NavigationProp>()
-    const {openModal} = useModalControls()
+export function ListsScreen({}: Props) {
+  const pal = usePalette('default')
+  const setMinimalShellMode = useSetMinimalShellMode()
+  const {isMobile} = useWebMediaQueries()
+  const navigation = useNavigation<NavigationProp>()
+  const {openModal} = useModalControls()
 
-    useFocusEffect(
-      React.useCallback(() => {
-        setMinimalShellMode(false)
-      }, [setMinimalShellMode]),
-    )
+  useFocusEffect(
+    React.useCallback(() => {
+      setMinimalShellMode(false)
+    }, [setMinimalShellMode]),
+  )
 
-    const onPressNewList = React.useCallback(() => {
-      openModal({
-        name: 'create-or-edit-list',
-        purpose: 'app.bsky.graph.defs#curatelist',
-        onSave: (uri: string) => {
-          try {
-            const urip = new AtUri(uri)
-            navigation.navigate('ProfileList', {
-              name: urip.hostname,
-              rkey: urip.rkey,
-            })
-          } catch {}
-        },
-      })
-    }, [openModal, navigation])
+  const onPressNewList = React.useCallback(() => {
+    openModal({
+      name: 'create-or-edit-list',
+      purpose: 'app.bsky.graph.defs#curatelist',
+      onSave: (uri: string) => {
+        try {
+          const urip = new AtUri(uri)
+          navigation.navigate('ProfileList', {
+            name: urip.hostname,
+            rkey: urip.rkey,
+          })
+        } catch {}
+      },
+    })
+  }, [openModal, navigation])
 
-    return (
-      <View style={s.hContentRegion} testID="listsScreen">
-        <SimpleViewHeader
-          showBackButton={isMobile}
-          style={
-            !isMobile && [pal.border, {borderLeftWidth: 1, borderRightWidth: 1}]
-          }>
-          <View style={{flex: 1}}>
-            <Text type="title-lg" style={[pal.text, {fontWeight: 'bold'}]}>
-              <Trans>User Lists</Trans>
+  return (
+    <View style={s.hContentRegion} testID="listsScreen">
+      <SimpleViewHeader
+        showBackButton={isMobile}
+        style={
+          !isMobile && [pal.border, {borderLeftWidth: 1, borderRightWidth: 1}]
+        }>
+        <View style={{flex: 1}}>
+          <Text type="title-lg" style={[pal.text, {fontWeight: 'bold'}]}>
+            <Trans>User Lists</Trans>
+          </Text>
+          <Text style={pal.textLight}>
+            <Trans>Public, shareable lists which can drive feeds.</Trans>
+          </Text>
+        </View>
+        <View>
+          <Button
+            testID="newUserListBtn"
+            type="default"
+            onPress={onPressNewList}
+            style={{
+              flexDirection: 'row',
+              alignItems: 'center',
+              gap: 8,
+            }}>
+            <FontAwesomeIcon icon="plus" color={pal.colors.text} />
+            <Text type="button" style={pal.text}>
+              <Trans>New</Trans>
             </Text>
-            <Text style={pal.textLight}>
-              <Trans>Public, shareable lists which can drive feeds.</Trans>
-            </Text>
-          </View>
-          <View>
-            <Button
-              testID="newUserListBtn"
-              type="default"
-              onPress={onPressNewList}
-              style={{
-                flexDirection: 'row',
-                alignItems: 'center',
-                gap: 8,
-              }}>
-              <FontAwesomeIcon icon="plus" color={pal.colors.text} />
-              <Text type="button" style={pal.text}>
-                <Trans>New</Trans>
-              </Text>
-            </Button>
-          </View>
-        </SimpleViewHeader>
-        <MyLists filter="curate" style={s.flexGrow1} />
-      </View>
-    )
-  },
-)
+          </Button>
+        </View>
+      </SimpleViewHeader>
+      <MyLists filter="curate" style={s.flexGrow1} />
+    </View>
+  )
+}
diff --git a/src/view/screens/Moderation.tsx b/src/view/screens/Moderation.tsx
index 10b72fe9e..4d8d8cad7 100644
--- a/src/view/screens/Moderation.tsx
+++ b/src/view/screens/Moderation.tsx
@@ -6,7 +6,6 @@ import {
   FontAwesomeIconStyle,
 } from '@fortawesome/react-native-fontawesome'
 import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {s} from 'lib/styles'
 import {CenteredView} from '../com/util/Views'
 import {ViewHeader} from '../com/util/ViewHeader'
@@ -21,100 +20,98 @@ import {Trans, msg} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'Moderation'>
-export const ModerationScreen = withAuthRequired(
-  function Moderation({}: Props) {
-    const pal = usePalette('default')
-    const {_} = useLingui()
-    const setMinimalShellMode = useSetMinimalShellMode()
-    const {screen, track} = useAnalytics()
-    const {isTabletOrDesktop} = useWebMediaQueries()
-    const {openModal} = useModalControls()
+export function ModerationScreen({}: Props) {
+  const pal = usePalette('default')
+  const {_} = useLingui()
+  const setMinimalShellMode = useSetMinimalShellMode()
+  const {screen, track} = useAnalytics()
+  const {isTabletOrDesktop} = useWebMediaQueries()
+  const {openModal} = useModalControls()
 
-    useFocusEffect(
-      React.useCallback(() => {
-        screen('Moderation')
-        setMinimalShellMode(false)
-      }, [screen, setMinimalShellMode]),
-    )
+  useFocusEffect(
+    React.useCallback(() => {
+      screen('Moderation')
+      setMinimalShellMode(false)
+    }, [screen, setMinimalShellMode]),
+  )
 
-    const onPressContentFiltering = React.useCallback(() => {
-      track('Moderation:ContentfilteringButtonClicked')
-      openModal({name: 'content-filtering-settings'})
-    }, [track, openModal])
+  const onPressContentFiltering = React.useCallback(() => {
+    track('Moderation:ContentfilteringButtonClicked')
+    openModal({name: 'content-filtering-settings'})
+  }, [track, openModal])
 
-    return (
-      <CenteredView
-        style={[
-          s.hContentRegion,
-          pal.border,
-          isTabletOrDesktop ? styles.desktopContainer : pal.viewLight,
-        ]}
-        testID="moderationScreen">
-        <ViewHeader title={_(msg`Moderation`)} showOnDesktop />
-        <View style={styles.spacer} />
-        <TouchableOpacity
-          testID="contentFilteringBtn"
-          style={[styles.linkCard, pal.view]}
-          onPress={onPressContentFiltering}
-          accessibilityRole="tab"
-          accessibilityHint="Content filtering"
-          accessibilityLabel="">
-          <View style={[styles.iconContainer, pal.btn]}>
-            <FontAwesomeIcon
-              icon="eye"
-              style={pal.text as FontAwesomeIconStyle}
-            />
-          </View>
-          <Text type="lg" style={pal.text}>
-            <Trans>Content filtering</Trans>
-          </Text>
-        </TouchableOpacity>
-        <Link
-          testID="moderationlistsBtn"
-          style={[styles.linkCard, pal.view]}
-          href="/moderation/modlists">
-          <View style={[styles.iconContainer, pal.btn]}>
-            <FontAwesomeIcon
-              icon="users-slash"
-              style={pal.text as FontAwesomeIconStyle}
-            />
-          </View>
-          <Text type="lg" style={pal.text}>
-            <Trans>Moderation lists</Trans>
-          </Text>
-        </Link>
-        <Link
-          testID="mutedAccountsBtn"
-          style={[styles.linkCard, pal.view]}
-          href="/moderation/muted-accounts">
-          <View style={[styles.iconContainer, pal.btn]}>
-            <FontAwesomeIcon
-              icon="user-slash"
-              style={pal.text as FontAwesomeIconStyle}
-            />
-          </View>
-          <Text type="lg" style={pal.text}>
-            <Trans>Muted accounts</Trans>
-          </Text>
-        </Link>
-        <Link
-          testID="blockedAccountsBtn"
-          style={[styles.linkCard, pal.view]}
-          href="/moderation/blocked-accounts">
-          <View style={[styles.iconContainer, pal.btn]}>
-            <FontAwesomeIcon
-              icon="ban"
-              style={pal.text as FontAwesomeIconStyle}
-            />
-          </View>
-          <Text type="lg" style={pal.text}>
-            <Trans>Blocked accounts</Trans>
-          </Text>
-        </Link>
-      </CenteredView>
-    )
-  },
-)
+  return (
+    <CenteredView
+      style={[
+        s.hContentRegion,
+        pal.border,
+        isTabletOrDesktop ? styles.desktopContainer : pal.viewLight,
+      ]}
+      testID="moderationScreen">
+      <ViewHeader title={_(msg`Moderation`)} showOnDesktop />
+      <View style={styles.spacer} />
+      <TouchableOpacity
+        testID="contentFilteringBtn"
+        style={[styles.linkCard, pal.view]}
+        onPress={onPressContentFiltering}
+        accessibilityRole="tab"
+        accessibilityHint="Content filtering"
+        accessibilityLabel="">
+        <View style={[styles.iconContainer, pal.btn]}>
+          <FontAwesomeIcon
+            icon="eye"
+            style={pal.text as FontAwesomeIconStyle}
+          />
+        </View>
+        <Text type="lg" style={pal.text}>
+          <Trans>Content filtering</Trans>
+        </Text>
+      </TouchableOpacity>
+      <Link
+        testID="moderationlistsBtn"
+        style={[styles.linkCard, pal.view]}
+        href="/moderation/modlists">
+        <View style={[styles.iconContainer, pal.btn]}>
+          <FontAwesomeIcon
+            icon="users-slash"
+            style={pal.text as FontAwesomeIconStyle}
+          />
+        </View>
+        <Text type="lg" style={pal.text}>
+          <Trans>Moderation lists</Trans>
+        </Text>
+      </Link>
+      <Link
+        testID="mutedAccountsBtn"
+        style={[styles.linkCard, pal.view]}
+        href="/moderation/muted-accounts">
+        <View style={[styles.iconContainer, pal.btn]}>
+          <FontAwesomeIcon
+            icon="user-slash"
+            style={pal.text as FontAwesomeIconStyle}
+          />
+        </View>
+        <Text type="lg" style={pal.text}>
+          <Trans>Muted accounts</Trans>
+        </Text>
+      </Link>
+      <Link
+        testID="blockedAccountsBtn"
+        style={[styles.linkCard, pal.view]}
+        href="/moderation/blocked-accounts">
+        <View style={[styles.iconContainer, pal.btn]}>
+          <FontAwesomeIcon
+            icon="ban"
+            style={pal.text as FontAwesomeIconStyle}
+          />
+        </View>
+        <Text type="lg" style={pal.text}>
+          <Trans>Blocked accounts</Trans>
+        </Text>
+      </Link>
+    </CenteredView>
+  )
+}
 
 const styles = StyleSheet.create({
   desktopContainer: {
diff --git a/src/view/screens/ModerationBlockedAccounts.tsx b/src/view/screens/ModerationBlockedAccounts.tsx
index c03275f5d..8f6e2f729 100644
--- a/src/view/screens/ModerationBlockedAccounts.tsx
+++ b/src/view/screens/ModerationBlockedAccounts.tsx
@@ -10,7 +10,6 @@ import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
 import {Text} from '../com/util/text/Text'
 import {usePalette} from 'lib/hooks/usePalette'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {NativeStackScreenProps} from '@react-navigation/native-stack'
 import {CommonNavigatorParams} from 'lib/routes/types'
 import {useAnalytics} from 'lib/analytics/analytics'
@@ -30,146 +29,144 @@ type Props = NativeStackScreenProps<
   CommonNavigatorParams,
   'ModerationBlockedAccounts'
 >
-export const ModerationBlockedAccounts = withAuthRequired(
-  function ModerationBlockedAccountsImpl({}: Props) {
-    const pal = usePalette('default')
-    const {_} = useLingui()
-    const setMinimalShellMode = useSetMinimalShellMode()
-    const {isTabletOrDesktop} = useWebMediaQueries()
-    const {screen} = useAnalytics()
-    const [isPTRing, setIsPTRing] = React.useState(false)
-    const {
-      data,
-      isFetching,
-      isError,
-      error,
-      refetch,
-      hasNextPage,
-      fetchNextPage,
-      isFetchingNextPage,
-    } = useMyBlockedAccountsQuery()
-    const isEmpty = !isFetching && !data?.pages[0]?.blocks.length
-    const profiles = React.useMemo(() => {
-      if (data?.pages) {
-        return data.pages.flatMap(page => page.blocks)
-      }
-      return []
-    }, [data])
+export function ModerationBlockedAccounts({}: Props) {
+  const pal = usePalette('default')
+  const {_} = useLingui()
+  const setMinimalShellMode = useSetMinimalShellMode()
+  const {isTabletOrDesktop} = useWebMediaQueries()
+  const {screen} = useAnalytics()
+  const [isPTRing, setIsPTRing] = React.useState(false)
+  const {
+    data,
+    isFetching,
+    isError,
+    error,
+    refetch,
+    hasNextPage,
+    fetchNextPage,
+    isFetchingNextPage,
+  } = useMyBlockedAccountsQuery()
+  const isEmpty = !isFetching && !data?.pages[0]?.blocks.length
+  const profiles = React.useMemo(() => {
+    if (data?.pages) {
+      return data.pages.flatMap(page => page.blocks)
+    }
+    return []
+  }, [data])
 
-    useFocusEffect(
-      React.useCallback(() => {
-        screen('BlockedAccounts')
-        setMinimalShellMode(false)
-      }, [screen, setMinimalShellMode]),
-    )
+  useFocusEffect(
+    React.useCallback(() => {
+      screen('BlockedAccounts')
+      setMinimalShellMode(false)
+    }, [screen, setMinimalShellMode]),
+  )
 
-    const onRefresh = React.useCallback(async () => {
-      setIsPTRing(true)
-      try {
-        await refetch()
-      } catch (err) {
-        logger.error('Failed to refresh my muted accounts', {error: err})
-      }
-      setIsPTRing(false)
-    }, [refetch, setIsPTRing])
+  const onRefresh = React.useCallback(async () => {
+    setIsPTRing(true)
+    try {
+      await refetch()
+    } catch (err) {
+      logger.error('Failed to refresh my muted accounts', {error: err})
+    }
+    setIsPTRing(false)
+  }, [refetch, setIsPTRing])
 
-    const onEndReached = React.useCallback(async () => {
-      if (isFetching || !hasNextPage || isError) return
+  const onEndReached = React.useCallback(async () => {
+    if (isFetching || !hasNextPage || isError) return
 
-      try {
-        await fetchNextPage()
-      } catch (err) {
-        logger.error('Failed to load more of my muted accounts', {error: err})
-      }
-    }, [isFetching, hasNextPage, isError, fetchNextPage])
+    try {
+      await fetchNextPage()
+    } catch (err) {
+      logger.error('Failed to load more of my muted accounts', {error: err})
+    }
+  }, [isFetching, hasNextPage, isError, fetchNextPage])
 
-    const renderItem = ({
-      item,
-      index,
-    }: {
-      item: ActorDefs.ProfileView
-      index: number
-    }) => (
-      <ProfileCard
-        testID={`blockedAccount-${index}`}
-        key={item.did}
-        profile={item}
-      />
-    )
-    return (
-      <CenteredView
+  const renderItem = ({
+    item,
+    index,
+  }: {
+    item: ActorDefs.ProfileView
+    index: number
+  }) => (
+    <ProfileCard
+      testID={`blockedAccount-${index}`}
+      key={item.did}
+      profile={item}
+    />
+  )
+  return (
+    <CenteredView
+      style={[
+        styles.container,
+        isTabletOrDesktop && styles.containerDesktop,
+        pal.view,
+        pal.border,
+      ]}
+      testID="blockedAccountsScreen">
+      <ViewHeader title={_(msg`Blocked Accounts`)} showOnDesktop />
+      <Text
+        type="sm"
         style={[
-          styles.container,
-          isTabletOrDesktop && styles.containerDesktop,
-          pal.view,
-          pal.border,
-        ]}
-        testID="blockedAccountsScreen">
-        <ViewHeader title={_(msg`Blocked Accounts`)} showOnDesktop />
-        <Text
-          type="sm"
-          style={[
-            styles.description,
-            pal.text,
-            isTabletOrDesktop && styles.descriptionDesktop,
-          ]}>
-          <Trans>
-            Blocked accounts cannot reply in your threads, mention you, or
-            otherwise interact with you. You will not see their content and they
-            will be prevented from seeing yours.
-          </Trans>
-        </Text>
-        {isEmpty ? (
-          <View style={[pal.border, !isTabletOrDesktop && styles.flex1]}>
-            {isError ? (
-              <ErrorScreen
-                title="Oops!"
-                message={cleanError(error)}
-                onPressTryAgain={refetch}
-              />
-            ) : (
-              <View style={[styles.empty, pal.viewLight]}>
-                <Text type="lg" style={[pal.text, styles.emptyText]}>
-                  <Trans>
-                    You have not blocked any accounts yet. To block an account,
-                    go to their profile and selected "Block account" from the
-                    menu on their account.
-                  </Trans>
-                </Text>
-              </View>
-            )}
-          </View>
-        ) : (
-          <FlatList
-            style={[!isTabletOrDesktop && styles.flex1]}
-            data={profiles}
-            keyExtractor={(item: ActorDefs.ProfileView) => item.did}
-            refreshControl={
-              <RefreshControl
-                refreshing={isPTRing}
-                onRefresh={onRefresh}
-                tintColor={pal.colors.text}
-                titleColor={pal.colors.text}
-              />
-            }
-            onEndReached={onEndReached}
-            renderItem={renderItem}
-            initialNumToRender={15}
-            // FIXME(dan)
+          styles.description,
+          pal.text,
+          isTabletOrDesktop && styles.descriptionDesktop,
+        ]}>
+        <Trans>
+          Blocked accounts cannot reply in your threads, mention you, or
+          otherwise interact with you. You will not see their content and they
+          will be prevented from seeing yours.
+        </Trans>
+      </Text>
+      {isEmpty ? (
+        <View style={[pal.border, !isTabletOrDesktop && styles.flex1]}>
+          {isError ? (
+            <ErrorScreen
+              title="Oops!"
+              message={cleanError(error)}
+              onPressTryAgain={refetch}
+            />
+          ) : (
+            <View style={[styles.empty, pal.viewLight]}>
+              <Text type="lg" style={[pal.text, styles.emptyText]}>
+                <Trans>
+                  You have not blocked any accounts yet. To block an account, go
+                  to their profile and selected "Block account" from the menu on
+                  their account.
+                </Trans>
+              </Text>
+            </View>
+          )}
+        </View>
+      ) : (
+        <FlatList
+          style={[!isTabletOrDesktop && styles.flex1]}
+          data={profiles}
+          keyExtractor={(item: ActorDefs.ProfileView) => item.did}
+          refreshControl={
+            <RefreshControl
+              refreshing={isPTRing}
+              onRefresh={onRefresh}
+              tintColor={pal.colors.text}
+              titleColor={pal.colors.text}
+            />
+          }
+          onEndReached={onEndReached}
+          renderItem={renderItem}
+          initialNumToRender={15}
+          // FIXME(dan)
 
-            ListFooterComponent={() => (
-              <View style={styles.footer}>
-                {(isFetching || isFetchingNextPage) && <ActivityIndicator />}
-              </View>
-            )}
-            // @ts-ignore our .web version only -prf
-            desktopFixedHeight
-          />
-        )}
-      </CenteredView>
-    )
-  },
-)
+          ListFooterComponent={() => (
+            <View style={styles.footer}>
+              {(isFetching || isFetchingNextPage) && <ActivityIndicator />}
+            </View>
+          )}
+          // @ts-ignore our .web version only -prf
+          desktopFixedHeight
+        />
+      )}
+    </CenteredView>
+  )
+}
 
 const styles = StyleSheet.create({
   container: {
diff --git a/src/view/screens/ModerationModlists.tsx b/src/view/screens/ModerationModlists.tsx
index be0eb3850..145b35a42 100644
--- a/src/view/screens/ModerationModlists.tsx
+++ b/src/view/screens/ModerationModlists.tsx
@@ -4,7 +4,6 @@ import {useFocusEffect, useNavigation} from '@react-navigation/native'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
 import {AtUri} from '@atproto/api'
 import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {MyLists} from '#/view/com/lists/MyLists'
 import {Text} from 'view/com/util/text/Text'
 import {Button} from 'view/com/util/forms/Button'
@@ -17,70 +16,68 @@ import {useSetMinimalShellMode} from '#/state/shell'
 import {useModalControls} from '#/state/modals'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'ModerationModlists'>
-export const ModerationModlistsScreen = withAuthRequired(
-  function ModerationModlistsScreenImpl({}: Props) {
-    const pal = usePalette('default')
-    const setMinimalShellMode = useSetMinimalShellMode()
-    const {isMobile} = useWebMediaQueries()
-    const navigation = useNavigation<NavigationProp>()
-    const {openModal} = useModalControls()
+export function ModerationModlistsScreen({}: Props) {
+  const pal = usePalette('default')
+  const setMinimalShellMode = useSetMinimalShellMode()
+  const {isMobile} = useWebMediaQueries()
+  const navigation = useNavigation<NavigationProp>()
+  const {openModal} = useModalControls()
 
-    useFocusEffect(
-      React.useCallback(() => {
-        setMinimalShellMode(false)
-      }, [setMinimalShellMode]),
-    )
+  useFocusEffect(
+    React.useCallback(() => {
+      setMinimalShellMode(false)
+    }, [setMinimalShellMode]),
+  )
 
-    const onPressNewList = React.useCallback(() => {
-      openModal({
-        name: 'create-or-edit-list',
-        purpose: 'app.bsky.graph.defs#modlist',
-        onSave: (uri: string) => {
-          try {
-            const urip = new AtUri(uri)
-            navigation.navigate('ProfileList', {
-              name: urip.hostname,
-              rkey: urip.rkey,
-            })
-          } catch {}
-        },
-      })
-    }, [openModal, navigation])
+  const onPressNewList = React.useCallback(() => {
+    openModal({
+      name: 'create-or-edit-list',
+      purpose: 'app.bsky.graph.defs#modlist',
+      onSave: (uri: string) => {
+        try {
+          const urip = new AtUri(uri)
+          navigation.navigate('ProfileList', {
+            name: urip.hostname,
+            rkey: urip.rkey,
+          })
+        } catch {}
+      },
+    })
+  }, [openModal, navigation])
 
-    return (
-      <View style={s.hContentRegion} testID="moderationModlistsScreen">
-        <SimpleViewHeader
-          showBackButton={isMobile}
-          style={
-            !isMobile && [pal.border, {borderLeftWidth: 1, borderRightWidth: 1}]
-          }>
-          <View style={{flex: 1}}>
-            <Text type="title-lg" style={[pal.text, {fontWeight: 'bold'}]}>
-              Moderation Lists
+  return (
+    <View style={s.hContentRegion} testID="moderationModlistsScreen">
+      <SimpleViewHeader
+        showBackButton={isMobile}
+        style={
+          !isMobile && [pal.border, {borderLeftWidth: 1, borderRightWidth: 1}]
+        }>
+        <View style={{flex: 1}}>
+          <Text type="title-lg" style={[pal.text, {fontWeight: 'bold'}]}>
+            Moderation Lists
+          </Text>
+          <Text style={pal.textLight}>
+            Public, shareable lists of users to mute or block in bulk.
+          </Text>
+        </View>
+        <View>
+          <Button
+            testID="newModListBtn"
+            type="default"
+            onPress={onPressNewList}
+            style={{
+              flexDirection: 'row',
+              alignItems: 'center',
+              gap: 8,
+            }}>
+            <FontAwesomeIcon icon="plus" color={pal.colors.text} />
+            <Text type="button" style={pal.text}>
+              New
             </Text>
-            <Text style={pal.textLight}>
-              Public, shareable lists of users to mute or block in bulk.
-            </Text>
-          </View>
-          <View>
-            <Button
-              testID="newModListBtn"
-              type="default"
-              onPress={onPressNewList}
-              style={{
-                flexDirection: 'row',
-                alignItems: 'center',
-                gap: 8,
-              }}>
-              <FontAwesomeIcon icon="plus" color={pal.colors.text} />
-              <Text type="button" style={pal.text}>
-                New
-              </Text>
-            </Button>
-          </View>
-        </SimpleViewHeader>
-        <MyLists filter="mod" style={s.flexGrow1} />
-      </View>
-    )
-  },
-)
+          </Button>
+        </View>
+      </SimpleViewHeader>
+      <MyLists filter="mod" style={s.flexGrow1} />
+    </View>
+  )
+}
diff --git a/src/view/screens/ModerationMutedAccounts.tsx b/src/view/screens/ModerationMutedAccounts.tsx
index c0ff17eb4..41aee9f2f 100644
--- a/src/view/screens/ModerationMutedAccounts.tsx
+++ b/src/view/screens/ModerationMutedAccounts.tsx
@@ -10,7 +10,6 @@ import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
 import {Text} from '../com/util/text/Text'
 import {usePalette} from 'lib/hooks/usePalette'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {NativeStackScreenProps} from '@react-navigation/native-stack'
 import {CommonNavigatorParams} from 'lib/routes/types'
 import {useAnalytics} from 'lib/analytics/analytics'
@@ -30,145 +29,143 @@ type Props = NativeStackScreenProps<
   CommonNavigatorParams,
   'ModerationMutedAccounts'
 >
-export const ModerationMutedAccounts = withAuthRequired(
-  function ModerationMutedAccountsImpl({}: Props) {
-    const pal = usePalette('default')
-    const {_} = useLingui()
-    const setMinimalShellMode = useSetMinimalShellMode()
-    const {isTabletOrDesktop} = useWebMediaQueries()
-    const {screen} = useAnalytics()
-    const [isPTRing, setIsPTRing] = React.useState(false)
-    const {
-      data,
-      isFetching,
-      isError,
-      error,
-      refetch,
-      hasNextPage,
-      fetchNextPage,
-      isFetchingNextPage,
-    } = useMyMutedAccountsQuery()
-    const isEmpty = !isFetching && !data?.pages[0]?.mutes.length
-    const profiles = React.useMemo(() => {
-      if (data?.pages) {
-        return data.pages.flatMap(page => page.mutes)
-      }
-      return []
-    }, [data])
+export function ModerationMutedAccounts({}: Props) {
+  const pal = usePalette('default')
+  const {_} = useLingui()
+  const setMinimalShellMode = useSetMinimalShellMode()
+  const {isTabletOrDesktop} = useWebMediaQueries()
+  const {screen} = useAnalytics()
+  const [isPTRing, setIsPTRing] = React.useState(false)
+  const {
+    data,
+    isFetching,
+    isError,
+    error,
+    refetch,
+    hasNextPage,
+    fetchNextPage,
+    isFetchingNextPage,
+  } = useMyMutedAccountsQuery()
+  const isEmpty = !isFetching && !data?.pages[0]?.mutes.length
+  const profiles = React.useMemo(() => {
+    if (data?.pages) {
+      return data.pages.flatMap(page => page.mutes)
+    }
+    return []
+  }, [data])
 
-    useFocusEffect(
-      React.useCallback(() => {
-        screen('MutedAccounts')
-        setMinimalShellMode(false)
-      }, [screen, setMinimalShellMode]),
-    )
+  useFocusEffect(
+    React.useCallback(() => {
+      screen('MutedAccounts')
+      setMinimalShellMode(false)
+    }, [screen, setMinimalShellMode]),
+  )
 
-    const onRefresh = React.useCallback(async () => {
-      setIsPTRing(true)
-      try {
-        await refetch()
-      } catch (err) {
-        logger.error('Failed to refresh my muted accounts', {error: err})
-      }
-      setIsPTRing(false)
-    }, [refetch, setIsPTRing])
+  const onRefresh = React.useCallback(async () => {
+    setIsPTRing(true)
+    try {
+      await refetch()
+    } catch (err) {
+      logger.error('Failed to refresh my muted accounts', {error: err})
+    }
+    setIsPTRing(false)
+  }, [refetch, setIsPTRing])
 
-    const onEndReached = React.useCallback(async () => {
-      if (isFetching || !hasNextPage || isError) return
+  const onEndReached = React.useCallback(async () => {
+    if (isFetching || !hasNextPage || isError) return
 
-      try {
-        await fetchNextPage()
-      } catch (err) {
-        logger.error('Failed to load more of my muted accounts', {error: err})
-      }
-    }, [isFetching, hasNextPage, isError, fetchNextPage])
+    try {
+      await fetchNextPage()
+    } catch (err) {
+      logger.error('Failed to load more of my muted accounts', {error: err})
+    }
+  }, [isFetching, hasNextPage, isError, fetchNextPage])
 
-    const renderItem = ({
-      item,
-      index,
-    }: {
-      item: ActorDefs.ProfileView
-      index: number
-    }) => (
-      <ProfileCard
-        testID={`mutedAccount-${index}`}
-        key={item.did}
-        profile={item}
-      />
-    )
-    return (
-      <CenteredView
+  const renderItem = ({
+    item,
+    index,
+  }: {
+    item: ActorDefs.ProfileView
+    index: number
+  }) => (
+    <ProfileCard
+      testID={`mutedAccount-${index}`}
+      key={item.did}
+      profile={item}
+    />
+  )
+  return (
+    <CenteredView
+      style={[
+        styles.container,
+        isTabletOrDesktop && styles.containerDesktop,
+        pal.view,
+        pal.border,
+      ]}
+      testID="mutedAccountsScreen">
+      <ViewHeader title={_(msg`Muted Accounts`)} showOnDesktop />
+      <Text
+        type="sm"
         style={[
-          styles.container,
-          isTabletOrDesktop && styles.containerDesktop,
-          pal.view,
-          pal.border,
-        ]}
-        testID="mutedAccountsScreen">
-        <ViewHeader title={_(msg`Muted Accounts`)} showOnDesktop />
-        <Text
-          type="sm"
-          style={[
-            styles.description,
-            pal.text,
-            isTabletOrDesktop && styles.descriptionDesktop,
-          ]}>
-          <Trans>
-            Muted accounts have their posts removed from your feed and from your
-            notifications. Mutes are completely private.
-          </Trans>
-        </Text>
-        {isEmpty ? (
-          <View style={[pal.border, !isTabletOrDesktop && styles.flex1]}>
-            {isError ? (
-              <ErrorScreen
-                title="Oops!"
-                message={cleanError(error)}
-                onPressTryAgain={refetch}
-              />
-            ) : (
-              <View style={[styles.empty, pal.viewLight]}>
-                <Text type="lg" style={[pal.text, styles.emptyText]}>
-                  <Trans>
-                    You have not muted any accounts yet. To mute an account, go
-                    to their profile and selected "Mute account" from the menu
-                    on their account.
-                  </Trans>
-                </Text>
-              </View>
-            )}
-          </View>
-        ) : (
-          <FlatList
-            style={[!isTabletOrDesktop && styles.flex1]}
-            data={profiles}
-            keyExtractor={item => item.did}
-            refreshControl={
-              <RefreshControl
-                refreshing={isPTRing}
-                onRefresh={onRefresh}
-                tintColor={pal.colors.text}
-                titleColor={pal.colors.text}
-              />
-            }
-            onEndReached={onEndReached}
-            renderItem={renderItem}
-            initialNumToRender={15}
-            // FIXME(dan)
+          styles.description,
+          pal.text,
+          isTabletOrDesktop && styles.descriptionDesktop,
+        ]}>
+        <Trans>
+          Muted accounts have their posts removed from your feed and from your
+          notifications. Mutes are completely private.
+        </Trans>
+      </Text>
+      {isEmpty ? (
+        <View style={[pal.border, !isTabletOrDesktop && styles.flex1]}>
+          {isError ? (
+            <ErrorScreen
+              title="Oops!"
+              message={cleanError(error)}
+              onPressTryAgain={refetch}
+            />
+          ) : (
+            <View style={[styles.empty, pal.viewLight]}>
+              <Text type="lg" style={[pal.text, styles.emptyText]}>
+                <Trans>
+                  You have not muted any accounts yet. To mute an account, go to
+                  their profile and selected "Mute account" from the menu on
+                  their account.
+                </Trans>
+              </Text>
+            </View>
+          )}
+        </View>
+      ) : (
+        <FlatList
+          style={[!isTabletOrDesktop && styles.flex1]}
+          data={profiles}
+          keyExtractor={item => item.did}
+          refreshControl={
+            <RefreshControl
+              refreshing={isPTRing}
+              onRefresh={onRefresh}
+              tintColor={pal.colors.text}
+              titleColor={pal.colors.text}
+            />
+          }
+          onEndReached={onEndReached}
+          renderItem={renderItem}
+          initialNumToRender={15}
+          // FIXME(dan)
 
-            ListFooterComponent={() => (
-              <View style={styles.footer}>
-                {(isFetching || isFetchingNextPage) && <ActivityIndicator />}
-              </View>
-            )}
-            // @ts-ignore our .web version only -prf
-            desktopFixedHeight
-          />
-        )}
-      </CenteredView>
-    )
-  },
-)
+          ListFooterComponent={() => (
+            <View style={styles.footer}>
+              {(isFetching || isFetchingNextPage) && <ActivityIndicator />}
+            </View>
+          )}
+          // @ts-ignore our .web version only -prf
+          desktopFixedHeight
+        />
+      )}
+    </CenteredView>
+  )
+}
 
 const styles = StyleSheet.create({
   container: {
diff --git a/src/view/screens/Notifications.tsx b/src/view/screens/Notifications.tsx
index 4ed9c7f74..8516d1667 100644
--- a/src/view/screens/Notifications.tsx
+++ b/src/view/screens/Notifications.tsx
@@ -6,7 +6,6 @@ import {
   NativeStackScreenProps,
   NotificationsTabNavigatorParams,
 } from 'lib/routes/types'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {ViewHeader} from '../com/util/ViewHeader'
 import {Feed} from '../com/notifications/Feed'
 import {TextLink} from 'view/com/util/Link'
@@ -28,102 +27,100 @@ type Props = NativeStackScreenProps<
   NotificationsTabNavigatorParams,
   'Notifications'
 >
-export const NotificationsScreen = withAuthRequired(
-  function NotificationsScreenImpl({}: Props) {
-    const {_} = useLingui()
-    const setMinimalShellMode = useSetMinimalShellMode()
-    const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll()
-    const scrollElRef = React.useRef<FlatList>(null)
-    const {screen} = useAnalytics()
-    const pal = usePalette('default')
-    const {isDesktop} = useWebMediaQueries()
-    const unreadNotifs = useUnreadNotifications()
-    const queryClient = useQueryClient()
-    const hasNew = !!unreadNotifs
+export function NotificationsScreen({}: Props) {
+  const {_} = useLingui()
+  const setMinimalShellMode = useSetMinimalShellMode()
+  const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll()
+  const scrollElRef = React.useRef<FlatList>(null)
+  const {screen} = useAnalytics()
+  const pal = usePalette('default')
+  const {isDesktop} = useWebMediaQueries()
+  const unreadNotifs = useUnreadNotifications()
+  const queryClient = useQueryClient()
+  const hasNew = !!unreadNotifs
 
-    // event handlers
-    // =
-    const scrollToTop = React.useCallback(() => {
-      scrollElRef.current?.scrollToOffset({offset: 0})
-      resetMainScroll()
-    }, [scrollElRef, resetMainScroll])
+  // event handlers
+  // =
+  const scrollToTop = React.useCallback(() => {
+    scrollElRef.current?.scrollToOffset({offset: 0})
+    resetMainScroll()
+  }, [scrollElRef, resetMainScroll])
 
-    const onPressLoadLatest = React.useCallback(() => {
-      scrollToTop()
-      queryClient.invalidateQueries({
-        queryKey: NOTIFS_RQKEY(),
-      })
-    }, [scrollToTop, queryClient])
+  const onPressLoadLatest = React.useCallback(() => {
+    scrollToTop()
+    queryClient.invalidateQueries({
+      queryKey: NOTIFS_RQKEY(),
+    })
+  }, [scrollToTop, queryClient])
 
-    // on-visible setup
-    // =
-    useFocusEffect(
-      React.useCallback(() => {
-        setMinimalShellMode(false)
-        logger.debug('NotificationsScreen: Updating feed')
-        screen('Notifications')
-        return listenSoftReset(onPressLoadLatest)
-      }, [screen, onPressLoadLatest, setMinimalShellMode]),
-    )
+  // on-visible setup
+  // =
+  useFocusEffect(
+    React.useCallback(() => {
+      setMinimalShellMode(false)
+      logger.debug('NotificationsScreen: Updating feed')
+      screen('Notifications')
+      return listenSoftReset(onPressLoadLatest)
+    }, [screen, onPressLoadLatest, setMinimalShellMode]),
+  )
 
-    const ListHeaderComponent = React.useCallback(() => {
-      if (isDesktop) {
-        return (
-          <View
-            style={[
-              pal.view,
-              {
-                flexDirection: 'row',
-                alignItems: 'center',
-                justifyContent: 'space-between',
-                paddingHorizontal: 18,
-                paddingVertical: 12,
-              },
-            ]}>
-            <TextLink
-              type="title-lg"
-              href="/notifications"
-              style={[pal.text, {fontWeight: 'bold'}]}
-              text={
-                <>
-                  <Trans>Notifications</Trans>{' '}
-                  {hasNew && (
-                    <View
-                      style={{
-                        top: -8,
-                        backgroundColor: colors.blue3,
-                        width: 8,
-                        height: 8,
-                        borderRadius: 4,
-                      }}
-                    />
-                  )}
-                </>
-              }
-              onPress={emitSoftReset}
-            />
-          </View>
-        )
-      }
-      return <></>
-    }, [isDesktop, pal, hasNew])
+  const ListHeaderComponent = React.useCallback(() => {
+    if (isDesktop) {
+      return (
+        <View
+          style={[
+            pal.view,
+            {
+              flexDirection: 'row',
+              alignItems: 'center',
+              justifyContent: 'space-between',
+              paddingHorizontal: 18,
+              paddingVertical: 12,
+            },
+          ]}>
+          <TextLink
+            type="title-lg"
+            href="/notifications"
+            style={[pal.text, {fontWeight: 'bold'}]}
+            text={
+              <>
+                <Trans>Notifications</Trans>{' '}
+                {hasNew && (
+                  <View
+                    style={{
+                      top: -8,
+                      backgroundColor: colors.blue3,
+                      width: 8,
+                      height: 8,
+                      borderRadius: 4,
+                    }}
+                  />
+                )}
+              </>
+            }
+            onPress={emitSoftReset}
+          />
+        </View>
+      )
+    }
+    return <></>
+  }, [isDesktop, pal, hasNew])
 
-    return (
-      <View testID="notificationsScreen" style={s.hContentRegion}>
-        <ViewHeader title={_(msg`Notifications`)} canGoBack={false} />
-        <Feed
-          onScroll={onMainScroll}
-          scrollElRef={scrollElRef}
-          ListHeaderComponent={ListHeaderComponent}
+  return (
+    <View testID="notificationsScreen" style={s.hContentRegion}>
+      <ViewHeader title={_(msg`Notifications`)} canGoBack={false} />
+      <Feed
+        onScroll={onMainScroll}
+        scrollElRef={scrollElRef}
+        ListHeaderComponent={ListHeaderComponent}
+      />
+      {(isScrolledDown || hasNew) && (
+        <LoadLatestBtn
+          onPress={onPressLoadLatest}
+          label={_(msg`Load new notifications`)}
+          showIndicator={hasNew}
         />
-        {(isScrolledDown || hasNew) && (
-          <LoadLatestBtn
-            onPress={onPressLoadLatest}
-            label={_(msg`Load new notifications`)}
-            showIndicator={hasNew}
-          />
-        )}
-      </View>
-    )
-  },
-)
+      )}
+    </View>
+  )
+}
diff --git a/src/view/screens/PostLikedBy.tsx b/src/view/screens/PostLikedBy.tsx
index 2209310d0..7cbb81102 100644
--- a/src/view/screens/PostLikedBy.tsx
+++ b/src/view/screens/PostLikedBy.tsx
@@ -2,7 +2,6 @@ import React from 'react'
 import {View} from 'react-native'
 import {useFocusEffect} from '@react-navigation/native'
 import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {ViewHeader} from '../com/util/ViewHeader'
 import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy'
 import {makeRecordUri} from 'lib/strings/url-helpers'
@@ -11,25 +10,22 @@ import {msg} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostLikedBy'>
-export const PostLikedByScreen = withAuthRequired(
-  ({route}: Props) => {
-    const setMinimalShellMode = useSetMinimalShellMode()
-    const {name, rkey} = route.params
-    const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey)
-    const {_} = useLingui()
+export const PostLikedByScreen = ({route}: Props) => {
+  const setMinimalShellMode = useSetMinimalShellMode()
+  const {name, rkey} = route.params
+  const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey)
+  const {_} = useLingui()
 
-    useFocusEffect(
-      React.useCallback(() => {
-        setMinimalShellMode(false)
-      }, [setMinimalShellMode]),
-    )
+  useFocusEffect(
+    React.useCallback(() => {
+      setMinimalShellMode(false)
+    }, [setMinimalShellMode]),
+  )
 
-    return (
-      <View>
-        <ViewHeader title={_(msg`Liked by`)} />
-        <PostLikedByComponent uri={uri} />
-      </View>
-    )
-  },
-  {isPublic: true},
-)
+  return (
+    <View>
+      <ViewHeader title={_(msg`Liked by`)} />
+      <PostLikedByComponent uri={uri} />
+    </View>
+  )
+}
diff --git a/src/view/screens/PostRepostedBy.tsx b/src/view/screens/PostRepostedBy.tsx
index 5b3b5f8fa..de95f33bf 100644
--- a/src/view/screens/PostRepostedBy.tsx
+++ b/src/view/screens/PostRepostedBy.tsx
@@ -1,7 +1,6 @@
 import React from 'react'
 import {View} from 'react-native'
 import {useFocusEffect} from '@react-navigation/native'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
 import {ViewHeader} from '../com/util/ViewHeader'
 import {PostRepostedBy as PostRepostedByComponent} from '../com/post-thread/PostRepostedBy'
@@ -11,25 +10,22 @@ import {useLingui} from '@lingui/react'
 import {msg} from '@lingui/macro'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostRepostedBy'>
-export const PostRepostedByScreen = withAuthRequired(
-  ({route}: Props) => {
-    const {name, rkey} = route.params
-    const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey)
-    const setMinimalShellMode = useSetMinimalShellMode()
-    const {_} = useLingui()
+export const PostRepostedByScreen = ({route}: Props) => {
+  const {name, rkey} = route.params
+  const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey)
+  const setMinimalShellMode = useSetMinimalShellMode()
+  const {_} = useLingui()
 
-    useFocusEffect(
-      React.useCallback(() => {
-        setMinimalShellMode(false)
-      }, [setMinimalShellMode]),
-    )
+  useFocusEffect(
+    React.useCallback(() => {
+      setMinimalShellMode(false)
+    }, [setMinimalShellMode]),
+  )
 
-    return (
-      <View>
-        <ViewHeader title={_(msg`Reposted by`)} />
-        <PostRepostedByComponent uri={uri} />
-      </View>
-    )
-  },
-  {isPublic: true},
-)
+  return (
+    <View>
+      <ViewHeader title={_(msg`Reposted by`)} />
+      <PostRepostedByComponent uri={uri} />
+    </View>
+  )
+}
diff --git a/src/view/screens/PostThread.tsx b/src/view/screens/PostThread.tsx
index 11574e283..4b1f51748 100644
--- a/src/view/screens/PostThread.tsx
+++ b/src/view/screens/PostThread.tsx
@@ -5,7 +5,6 @@ import {useFocusEffect} from '@react-navigation/native'
 import {useQueryClient} from '@tanstack/react-query'
 import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
 import {makeRecordUri} from 'lib/strings/url-helpers'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {ViewHeader} from '../com/util/ViewHeader'
 import {PostThread as PostThreadComponent} from '../com/post-thread/PostThread'
 import {ComposePrompt} from 'view/com/composer/Prompt'
@@ -27,85 +26,82 @@ import {CenteredView} from '../com/util/Views'
 import {useComposerControls} from '#/state/shell/composer'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostThread'>
-export const PostThreadScreen = withAuthRequired(
-  function PostThreadScreenImpl({route}: Props) {
-    const queryClient = useQueryClient()
-    const {_} = useLingui()
-    const {fabMinimalShellTransform} = useMinimalShellMode()
-    const setMinimalShellMode = useSetMinimalShellMode()
-    const {openComposer} = useComposerControls()
-    const safeAreaInsets = useSafeAreaInsets()
-    const {name, rkey} = route.params
-    const {isMobile} = useWebMediaQueries()
-    const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey)
-    const {data: resolvedUri, error: uriError} = useResolveUriQuery(uri)
+export function PostThreadScreen({route}: Props) {
+  const queryClient = useQueryClient()
+  const {_} = useLingui()
+  const {fabMinimalShellTransform} = useMinimalShellMode()
+  const setMinimalShellMode = useSetMinimalShellMode()
+  const {openComposer} = useComposerControls()
+  const safeAreaInsets = useSafeAreaInsets()
+  const {name, rkey} = route.params
+  const {isMobile} = useWebMediaQueries()
+  const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey)
+  const {data: resolvedUri, error: uriError} = useResolveUriQuery(uri)
 
-    useFocusEffect(
-      React.useCallback(() => {
-        setMinimalShellMode(false)
-      }, [setMinimalShellMode]),
-    )
+  useFocusEffect(
+    React.useCallback(() => {
+      setMinimalShellMode(false)
+    }, [setMinimalShellMode]),
+  )
 
-    const onPressReply = React.useCallback(() => {
-      if (!resolvedUri) {
-        return
-      }
-      const thread = queryClient.getQueryData<ThreadNode>(
-        POST_THREAD_RQKEY(resolvedUri.uri),
-      )
-      if (thread?.type !== 'post') {
-        return
-      }
-      openComposer({
-        replyTo: {
-          uri: thread.post.uri,
-          cid: thread.post.cid,
-          text: thread.record.text,
-          author: {
-            handle: thread.post.author.handle,
-            displayName: thread.post.author.displayName,
-            avatar: thread.post.author.avatar,
-          },
+  const onPressReply = React.useCallback(() => {
+    if (!resolvedUri) {
+      return
+    }
+    const thread = queryClient.getQueryData<ThreadNode>(
+      POST_THREAD_RQKEY(resolvedUri.uri),
+    )
+    if (thread?.type !== 'post') {
+      return
+    }
+    openComposer({
+      replyTo: {
+        uri: thread.post.uri,
+        cid: thread.post.cid,
+        text: thread.record.text,
+        author: {
+          handle: thread.post.author.handle,
+          displayName: thread.post.author.displayName,
+          avatar: thread.post.author.avatar,
         },
-        onPost: () =>
-          queryClient.invalidateQueries({
-            queryKey: POST_THREAD_RQKEY(resolvedUri.uri || ''),
-          }),
-      })
-    }, [openComposer, queryClient, resolvedUri])
+      },
+      onPost: () =>
+        queryClient.invalidateQueries({
+          queryKey: POST_THREAD_RQKEY(resolvedUri.uri || ''),
+        }),
+    })
+  }, [openComposer, queryClient, resolvedUri])
 
-    return (
-      <View style={s.hContentRegion}>
-        {isMobile && <ViewHeader title={_(msg`Post`)} />}
-        <View style={s.flex1}>
-          {uriError ? (
-            <CenteredView>
-              <ErrorMessage message={String(uriError)} />
-            </CenteredView>
-          ) : (
-            <PostThreadComponent
-              uri={resolvedUri?.uri}
-              onPressReply={onPressReply}
-            />
-          )}
-        </View>
-        {isMobile && (
-          <Animated.View
-            style={[
-              styles.prompt,
-              fabMinimalShellTransform,
-              {
-                bottom: clamp(safeAreaInsets.bottom, 15, 30),
-              },
-            ]}>
-            <ComposePrompt onPressCompose={onPressReply} />
-          </Animated.View>
+  return (
+    <View style={s.hContentRegion}>
+      {isMobile && <ViewHeader title={_(msg`Post`)} />}
+      <View style={s.flex1}>
+        {uriError ? (
+          <CenteredView>
+            <ErrorMessage message={String(uriError)} />
+          </CenteredView>
+        ) : (
+          <PostThreadComponent
+            uri={resolvedUri?.uri}
+            onPressReply={onPressReply}
+          />
         )}
       </View>
-    )
-  },
-  {isPublic: true},
-)
+      {isMobile && (
+        <Animated.View
+          style={[
+            styles.prompt,
+            fabMinimalShellTransform,
+            {
+              bottom: clamp(safeAreaInsets.bottom, 15, 30),
+            },
+          ]}>
+          <ComposePrompt onPressCompose={onPressReply} />
+        </Animated.View>
+      )}
+    </View>
+  )
+}
 
 const styles = StyleSheet.create({
   prompt: {
diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx
index 48c914054..8282b2105 100644
--- a/src/view/screens/Profile.tsx
+++ b/src/view/screens/Profile.tsx
@@ -5,7 +5,6 @@ import {AppBskyActorDefs, moderateProfile, ModerationOpts} from '@atproto/api'
 import {msg} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {ViewSelectorHandle} from '../com/util/ViewSelector'
 import {CenteredView, FlatList} from '../com/util/Views'
 import {ScreenHider} from 'view/com/util/moderation/ScreenHider'
@@ -43,83 +42,78 @@ interface SectionRef {
 }
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'Profile'>
-export const ProfileScreen = withAuthRequired(
-  function ProfileScreenImpl({route}: Props) {
-    const {currentAccount} = useSession()
-    const name =
-      route.params.name === 'me' ? currentAccount?.did : route.params.name
-    const moderationOpts = useModerationOpts()
-    const {
-      data: resolvedDid,
-      error: resolveError,
-      refetch: refetchDid,
-      isFetching: isFetchingDid,
-    } = useResolveDidQuery(name)
-    const {
-      data: profile,
-      error: profileError,
-      refetch: refetchProfile,
-      isFetching: isFetchingProfile,
-    } = useProfileQuery({
-      did: resolvedDid?.did,
-    })
+export function ProfileScreen({route}: Props) {
+  const {currentAccount} = useSession()
+  const name =
+    route.params.name === 'me' ? currentAccount?.did : route.params.name
+  const moderationOpts = useModerationOpts()
+  const {
+    data: resolvedDid,
+    error: resolveError,
+    refetch: refetchDid,
+    isFetching: isFetchingDid,
+  } = useResolveDidQuery(name)
+  const {
+    data: profile,
+    error: profileError,
+    refetch: refetchProfile,
+    isFetching: isFetchingProfile,
+  } = useProfileQuery({
+    did: resolvedDid?.did,
+  })
 
-    const onPressTryAgain = React.useCallback(() => {
-      if (resolveError) {
-        refetchDid()
-      } else {
-        refetchProfile()
-      }
-    }, [resolveError, refetchDid, refetchProfile])
-
-    if (isFetchingDid || isFetchingProfile || !moderationOpts) {
-      return (
-        <CenteredView>
-          <ProfileHeader
-            profile={null}
-            moderation={null}
-            isProfilePreview={true}
-          />
-        </CenteredView>
-      )
+  const onPressTryAgain = React.useCallback(() => {
+    if (resolveError) {
+      refetchDid()
+    } else {
+      refetchProfile()
     }
-    if (resolveError || profileError) {
-      return (
-        <CenteredView>
-          <ErrorScreen
-            testID="profileErrorScreen"
-            title="Oops!"
-            message={cleanError(resolveError || profileError)}
-            onPressTryAgain={onPressTryAgain}
-          />
-        </CenteredView>
-      )
-    }
-    if (profile && moderationOpts) {
-      return (
-        <ProfileScreenLoaded
-          profile={profile}
-          moderationOpts={moderationOpts}
-          hideBackButton={!!route.params.hideBackButton}
+  }, [resolveError, refetchDid, refetchProfile])
+
+  if (isFetchingDid || isFetchingProfile || !moderationOpts) {
+    return (
+      <CenteredView>
+        <ProfileHeader
+          profile={null}
+          moderation={null}
+          isProfilePreview={true}
         />
-      )
-    }
-    // should never happen
+      </CenteredView>
+    )
+  }
+  if (resolveError || profileError) {
     return (
       <CenteredView>
         <ErrorScreen
           testID="profileErrorScreen"
           title="Oops!"
-          message="Something went wrong and we're not sure what."
+          message={cleanError(resolveError || profileError)}
           onPressTryAgain={onPressTryAgain}
         />
       </CenteredView>
     )
-  },
-  {
-    isPublic: true,
-  },
-)
+  }
+  if (profile && moderationOpts) {
+    return (
+      <ProfileScreenLoaded
+        profile={profile}
+        moderationOpts={moderationOpts}
+        hideBackButton={!!route.params.hideBackButton}
+      />
+    )
+  }
+  // should never happen
+  return (
+    <CenteredView>
+      <ErrorScreen
+        testID="profileErrorScreen"
+        title="Oops!"
+        message="Something went wrong and we're not sure what."
+        onPressTryAgain={onPressTryAgain}
+      />
+    </CenteredView>
+  )
+}
 
 function ProfileScreenLoaded({
   profile: profileUnshadowed,
diff --git a/src/view/screens/ProfileFeed.tsx b/src/view/screens/ProfileFeed.tsx
index 642793eda..da01cfca6 100644
--- a/src/view/screens/ProfileFeed.tsx
+++ b/src/view/screens/ProfileFeed.tsx
@@ -16,7 +16,6 @@ import {CommonNavigatorParams} from 'lib/routes/types'
 import {makeRecordUri} from 'lib/strings/url-helpers'
 import {colors, s} from 'lib/styles'
 import {FeedDescriptor} from '#/state/queries/post-feed'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {PagerWithHeader} from 'view/com/pager/PagerWithHeader'
 import {ProfileSubpageHeader} from 'view/com/profile/ProfileSubpageHeader'
 import {Feed} from 'view/com/posts/Feed'
@@ -69,70 +68,65 @@ interface SectionRef {
 }
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFeed'>
-export const ProfileFeedScreen = withAuthRequired(
-  function ProfileFeedScreenImpl(props: Props) {
-    const {rkey, name: handleOrDid} = props.route.params
+export function ProfileFeedScreen(props: Props) {
+  const {rkey, name: handleOrDid} = props.route.params
 
-    const pal = usePalette('default')
-    const {_} = useLingui()
-    const navigation = useNavigation<NavigationProp>()
+  const pal = usePalette('default')
+  const {_} = useLingui()
+  const navigation = useNavigation<NavigationProp>()
 
-    const uri = useMemo(
-      () => makeRecordUri(handleOrDid, 'app.bsky.feed.generator', rkey),
-      [rkey, handleOrDid],
-    )
-    const {error, data: resolvedUri} = useResolveUriQuery(uri)
+  const uri = useMemo(
+    () => makeRecordUri(handleOrDid, 'app.bsky.feed.generator', rkey),
+    [rkey, handleOrDid],
+  )
+  const {error, data: resolvedUri} = useResolveUriQuery(uri)
 
-    const onPressBack = React.useCallback(() => {
-      if (navigation.canGoBack()) {
-        navigation.goBack()
-      } else {
-        navigation.navigate('Home')
-      }
-    }, [navigation])
-
-    if (error) {
-      return (
-        <CenteredView>
-          <View style={[pal.view, pal.border, styles.notFoundContainer]}>
-            <Text type="title-lg" style={[pal.text, s.mb10]}>
-              <Trans>Could not load feed</Trans>
-            </Text>
-            <Text type="md" style={[pal.text, s.mb20]}>
-              {error.toString()}
-            </Text>
-
-            <View style={{flexDirection: 'row'}}>
-              <Button
-                type="default"
-                accessibilityLabel={_(msg`Go Back`)}
-                accessibilityHint="Return to previous page"
-                onPress={onPressBack}
-                style={{flexShrink: 1}}>
-                <Text type="button" style={pal.text}>
-                  <Trans>Go Back</Trans>
-                </Text>
-              </Button>
-            </View>
-          </View>
-        </CenteredView>
-      )
+  const onPressBack = React.useCallback(() => {
+    if (navigation.canGoBack()) {
+      navigation.goBack()
+    } else {
+      navigation.navigate('Home')
     }
+  }, [navigation])
 
-    return resolvedUri ? (
-      <ProfileFeedScreenIntermediate feedUri={resolvedUri.uri} />
-    ) : (
+  if (error) {
+    return (
       <CenteredView>
-        <View style={s.p20}>
-          <ActivityIndicator size="large" />
+        <View style={[pal.view, pal.border, styles.notFoundContainer]}>
+          <Text type="title-lg" style={[pal.text, s.mb10]}>
+            <Trans>Could not load feed</Trans>
+          </Text>
+          <Text type="md" style={[pal.text, s.mb20]}>
+            {error.toString()}
+          </Text>
+
+          <View style={{flexDirection: 'row'}}>
+            <Button
+              type="default"
+              accessibilityLabel={_(msg`Go Back`)}
+              accessibilityHint="Return to previous page"
+              onPress={onPressBack}
+              style={{flexShrink: 1}}>
+              <Text type="button" style={pal.text}>
+                <Trans>Go Back</Trans>
+              </Text>
+            </Button>
+          </View>
         </View>
       </CenteredView>
     )
-  },
-  {
-    isPublic: true,
-  },
-)
+  }
+
+  return resolvedUri ? (
+    <ProfileFeedScreenIntermediate feedUri={resolvedUri.uri} />
+  ) : (
+    <CenteredView>
+      <View style={s.p20}>
+        <ActivityIndicator size="large" />
+      </View>
+    </CenteredView>
+  )
+}
 
 function ProfileFeedScreenIntermediate({feedUri}: {feedUri: string}) {
   const {data: preferences} = usePreferencesQuery()
diff --git a/src/view/screens/ProfileFeedLikedBy.tsx b/src/view/screens/ProfileFeedLikedBy.tsx
index 6399c8a0b..0460670e1 100644
--- a/src/view/screens/ProfileFeedLikedBy.tsx
+++ b/src/view/screens/ProfileFeedLikedBy.tsx
@@ -2,7 +2,6 @@ import React from 'react'
 import {View} from 'react-native'
 import {useFocusEffect} from '@react-navigation/native'
 import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {ViewHeader} from '../com/util/ViewHeader'
 import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy'
 import {makeRecordUri} from 'lib/strings/url-helpers'
@@ -11,25 +10,22 @@ import {useLingui} from '@lingui/react'
 import {msg} from '@lingui/macro'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFeedLikedBy'>
-export const ProfileFeedLikedByScreen = withAuthRequired(
-  ({route}: Props) => {
-    const setMinimalShellMode = useSetMinimalShellMode()
-    const {name, rkey} = route.params
-    const uri = makeRecordUri(name, 'app.bsky.feed.generator', rkey)
-    const {_} = useLingui()
+export const ProfileFeedLikedByScreen = ({route}: Props) => {
+  const setMinimalShellMode = useSetMinimalShellMode()
+  const {name, rkey} = route.params
+  const uri = makeRecordUri(name, 'app.bsky.feed.generator', rkey)
+  const {_} = useLingui()
 
-    useFocusEffect(
-      React.useCallback(() => {
-        setMinimalShellMode(false)
-      }, [setMinimalShellMode]),
-    )
+  useFocusEffect(
+    React.useCallback(() => {
+      setMinimalShellMode(false)
+    }, [setMinimalShellMode]),
+  )
 
-    return (
-      <View>
-        <ViewHeader title={_(msg`Liked by`)} />
-        <PostLikedByComponent uri={uri} />
-      </View>
-    )
-  },
-  {isPublic: true},
-)
+  return (
+    <View>
+      <ViewHeader title={_(msg`Liked by`)} />
+      <PostLikedByComponent uri={uri} />
+    </View>
+  )
+}
diff --git a/src/view/screens/ProfileFollowers.tsx b/src/view/screens/ProfileFollowers.tsx
index 71c0e4a9c..2cad08cb5 100644
--- a/src/view/screens/ProfileFollowers.tsx
+++ b/src/view/screens/ProfileFollowers.tsx
@@ -2,7 +2,6 @@ import React from 'react'
 import {View} from 'react-native'
 import {useFocusEffect} from '@react-navigation/native'
 import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {ViewHeader} from '../com/util/ViewHeader'
 import {ProfileFollowers as ProfileFollowersComponent} from '../com/profile/ProfileFollowers'
 import {useSetMinimalShellMode} from '#/state/shell'
@@ -10,24 +9,21 @@ import {useLingui} from '@lingui/react'
 import {msg} from '@lingui/macro'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFollowers'>
-export const ProfileFollowersScreen = withAuthRequired(
-  ({route}: Props) => {
-    const {name} = route.params
-    const setMinimalShellMode = useSetMinimalShellMode()
-    const {_} = useLingui()
+export const ProfileFollowersScreen = ({route}: Props) => {
+  const {name} = route.params
+  const setMinimalShellMode = useSetMinimalShellMode()
+  const {_} = useLingui()
 
-    useFocusEffect(
-      React.useCallback(() => {
-        setMinimalShellMode(false)
-      }, [setMinimalShellMode]),
-    )
+  useFocusEffect(
+    React.useCallback(() => {
+      setMinimalShellMode(false)
+    }, [setMinimalShellMode]),
+  )
 
-    return (
-      <View>
-        <ViewHeader title={_(msg`Followers`)} />
-        <ProfileFollowersComponent name={name} />
-      </View>
-    )
-  },
-  {isPublic: true},
-)
+  return (
+    <View>
+      <ViewHeader title={_(msg`Followers`)} />
+      <ProfileFollowersComponent name={name} />
+    </View>
+  )
+}
diff --git a/src/view/screens/ProfileFollows.tsx b/src/view/screens/ProfileFollows.tsx
index bb3f2040f..80502b98b 100644
--- a/src/view/screens/ProfileFollows.tsx
+++ b/src/view/screens/ProfileFollows.tsx
@@ -2,7 +2,6 @@ import React from 'react'
 import {View} from 'react-native'
 import {useFocusEffect} from '@react-navigation/native'
 import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {ViewHeader} from '../com/util/ViewHeader'
 import {ProfileFollows as ProfileFollowsComponent} from '../com/profile/ProfileFollows'
 import {useSetMinimalShellMode} from '#/state/shell'
@@ -10,24 +9,21 @@ import {useLingui} from '@lingui/react'
 import {msg} from '@lingui/macro'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFollows'>
-export const ProfileFollowsScreen = withAuthRequired(
-  ({route}: Props) => {
-    const {name} = route.params
-    const setMinimalShellMode = useSetMinimalShellMode()
-    const {_} = useLingui()
+export const ProfileFollowsScreen = ({route}: Props) => {
+  const {name} = route.params
+  const setMinimalShellMode = useSetMinimalShellMode()
+  const {_} = useLingui()
 
-    useFocusEffect(
-      React.useCallback(() => {
-        setMinimalShellMode(false)
-      }, [setMinimalShellMode]),
-    )
+  useFocusEffect(
+    React.useCallback(() => {
+      setMinimalShellMode(false)
+    }, [setMinimalShellMode]),
+  )
 
-    return (
-      <View>
-        <ViewHeader title={_(msg`Following`)} />
-        <ProfileFollowsComponent name={name} />
-      </View>
-    )
-  },
-  {isPublic: true},
-)
+  return (
+    <View>
+      <ViewHeader title={_(msg`Following`)} />
+      <ProfileFollowsComponent name={name} />
+    </View>
+  )
+}
diff --git a/src/view/screens/ProfileList.tsx b/src/view/screens/ProfileList.tsx
index a8c55250f..cc6d85e6f 100644
--- a/src/view/screens/ProfileList.tsx
+++ b/src/view/screens/ProfileList.tsx
@@ -12,7 +12,6 @@ import {useNavigation} from '@react-navigation/native'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
 import {AppBskyGraphDefs, AtUri, RichText as RichTextAPI} from '@atproto/api'
 import {useQueryClient} from '@tanstack/react-query'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {PagerWithHeader} from 'view/com/pager/PagerWithHeader'
 import {ProfileSubpageHeader} from 'view/com/profile/ProfileSubpageHeader'
 import {Feed} from 'view/com/posts/Feed'
@@ -64,42 +63,40 @@ interface SectionRef {
 }
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileList'>
-export const ProfileListScreen = withAuthRequired(
-  function ProfileListScreenImpl(props: Props) {
-    const {name: handleOrDid, rkey} = props.route.params
-    const {data: resolvedUri, error: resolveError} = useResolveUriQuery(
-      AtUri.make(handleOrDid, 'app.bsky.graph.list', rkey).toString(),
-    )
-    const {data: list, error: listError} = useListQuery(resolvedUri?.uri)
-
-    if (resolveError) {
-      return (
-        <CenteredView>
-          <ErrorScreen
-            error={`We're sorry, but we were unable to resolve this list. If this persists, please contact the list creator, @${handleOrDid}.`}
-          />
-        </CenteredView>
-      )
-    }
-    if (listError) {
-      return (
-        <CenteredView>
-          <ErrorScreen error={cleanError(listError)} />
-        </CenteredView>
-      )
-    }
+export function ProfileListScreen(props: Props) {
+  const {name: handleOrDid, rkey} = props.route.params
+  const {data: resolvedUri, error: resolveError} = useResolveUriQuery(
+    AtUri.make(handleOrDid, 'app.bsky.graph.list', rkey).toString(),
+  )
+  const {data: list, error: listError} = useListQuery(resolvedUri?.uri)
 
-    return resolvedUri && list ? (
-      <ProfileListScreenLoaded {...props} uri={resolvedUri.uri} list={list} />
-    ) : (
+  if (resolveError) {
+    return (
       <CenteredView>
-        <View style={s.p20}>
-          <ActivityIndicator size="large" />
-        </View>
+        <ErrorScreen
+          error={`We're sorry, but we were unable to resolve this list. If this persists, please contact the list creator, @${handleOrDid}.`}
+        />
       </CenteredView>
     )
-  },
-)
+  }
+  if (listError) {
+    return (
+      <CenteredView>
+        <ErrorScreen error={cleanError(listError)} />
+      </CenteredView>
+    )
+  }
+
+  return resolvedUri && list ? (
+    <ProfileListScreenLoaded {...props} uri={resolvedUri.uri} list={list} />
+  ) : (
+    <CenteredView>
+      <View style={s.p20}>
+        <ActivityIndicator size="large" />
+      </View>
+    </CenteredView>
+  )
+}
 
 function ProfileListScreenLoaded({
   route,
diff --git a/src/view/screens/SavedFeeds.tsx b/src/view/screens/SavedFeeds.tsx
index 4c13a2be1..640d76a5c 100644
--- a/src/view/screens/SavedFeeds.tsx
+++ b/src/view/screens/SavedFeeds.tsx
@@ -14,7 +14,6 @@ import {useAnalytics} from 'lib/analytics/analytics'
 import {usePalette} from 'lib/hooks/usePalette'
 import {CommonNavigatorParams} from 'lib/routes/types'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {ViewHeader} from 'view/com/util/ViewHeader'
 import {ScrollView, CenteredView} from 'view/com/util/Views'
 import {Text} from 'view/com/util/text/Text'
@@ -51,7 +50,7 @@ const HITSLOP_BOTTOM = {
 }
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'SavedFeeds'>
-export const SavedFeeds = withAuthRequired(function SavedFeedsImpl({}: Props) {
+export function SavedFeeds({}: Props) {
   const pal = usePalette('default')
   const {_} = useLingui()
   const {isMobile, isTabletOrDesktop} = useWebMediaQueries()
@@ -147,7 +146,7 @@ export const SavedFeeds = withAuthRequired(function SavedFeedsImpl({}: Props) {
       </ScrollView>
     </CenteredView>
   )
-})
+}
 
 function ListItem({
   feedUri,
diff --git a/src/view/screens/Search/index.tsx b/src/view/screens/Search/index.tsx
index 69130ecfd..a65149bf7 100644
--- a/src/view/screens/Search/index.tsx
+++ b/src/view/screens/Search/index.tsx
@@ -1,6 +1,3 @@
-import {withAuthRequired} from '#/view/com/auth/withAuthRequired'
 import {SearchScreenMobile} from '#/view/screens/Search/Search'
 
-export const SearchScreen = withAuthRequired(SearchScreenMobile, {
-  isPublic: true,
-})
+export const SearchScreen = SearchScreenMobile
diff --git a/src/view/screens/Search/index.web.tsx b/src/view/screens/Search/index.web.tsx
index 03fb7589c..8e039e3cd 100644
--- a/src/view/screens/Search/index.web.tsx
+++ b/src/view/screens/Search/index.web.tsx
@@ -1,6 +1,3 @@
-import {withAuthRequired} from '#/view/com/auth/withAuthRequired'
 import {SearchScreenDesktop} from '#/view/screens/Search/Search'
 
-export const SearchScreen = withAuthRequired(SearchScreenDesktop, {
-  isPublic: true,
-})
+export const SearchScreen = SearchScreenDesktop
diff --git a/src/view/screens/Settings.tsx b/src/view/screens/Settings.tsx
index cc4348fff..88cc2d532 100644
--- a/src/view/screens/Settings.tsx
+++ b/src/view/screens/Settings.tsx
@@ -20,7 +20,6 @@ import {
   FontAwesomeIconStyle,
 } from '@fortawesome/react-native-fontawesome'
 import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
-import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import * as AppInfo from 'lib/app-info'
 import {s, colors} from 'lib/styles'
 import {ScrollView} from '../com/util/Views'
@@ -141,7 +140,7 @@ function SettingsAccountCard({account}: {account: SessionAccount}) {
 }
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'Settings'>
-export const SettingsScreen = withAuthRequired(function Settings({}: Props) {
+export function SettingsScreen({}: Props) {
   const queryClient = useQueryClient()
   const colorMode = useColorMode()
   const setColorMode = useSetColorMode()
@@ -731,7 +730,7 @@ export const SettingsScreen = withAuthRequired(function Settings({}: Props) {
       </ScrollView>
     </View>
   )
-})
+}
 
 function EmailConfirmationNotice() {
   const pal = usePalette('default')
diff --git a/src/view/shell/createNativeStackNavigatorWithAuth.tsx b/src/view/shell/createNativeStackNavigatorWithAuth.tsx
new file mode 100644
index 000000000..c7b5d1d2e
--- /dev/null
+++ b/src/view/shell/createNativeStackNavigatorWithAuth.tsx
@@ -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)
diff --git a/src/view/shell/index.web.tsx b/src/view/shell/index.web.tsx
index 74477243d..38da860bd 100644
--- a/src/view/shell/index.web.tsx
+++ b/src/view/shell/index.web.tsx
@@ -1,7 +1,5 @@
 import React, {useEffect} from 'react'
 import {View, StyleSheet, TouchableOpacity} from 'react-native'
-import {DesktopLeftNav} from './desktop/LeftNav'
-import {DesktopRightNav} from './desktop/RightNav'
 import {ErrorBoundary} from '../com/util/ErrorBoundary'
 import {Lightbox} from '../com/lightbox/Lightbox'
 import {ModalsContainer} from '../com/modals/Modal'
@@ -11,27 +9,19 @@ import {s, colors} from 'lib/styles'
 import {RoutesContainer, FlatNavigator} from '../../Navigation'
 import {DrawerContent} from './Drawer'
 import {useWebMediaQueries} from '../../lib/hooks/useWebMediaQueries'
-import {BottomBarWeb} from './bottom-bar/BottomBarWeb'
 import {useNavigation} from '@react-navigation/native'
 import {NavigationProp} from 'lib/routes/types'
 import {useAuxClick} from 'lib/hooks/useAuxClick'
 import {t} from '@lingui/macro'
-import {
-  useIsDrawerOpen,
-  useSetDrawerOpen,
-  useOnboardingState,
-} from '#/state/shell'
+import {useIsDrawerOpen, useSetDrawerOpen} from '#/state/shell'
 import {useCloseAllActiveElements} from '#/state/util'
-import {useLoggedOutView} from '#/state/shell/logged-out'
 
 function ShellInner() {
   const isDrawerOpen = useIsDrawerOpen()
   const setDrawerOpen = useSetDrawerOpen()
-  const onboardingState = useOnboardingState()
-  const {isDesktop, isMobile} = useWebMediaQueries()
+  const {isDesktop} = useWebMediaQueries()
   const navigator = useNavigation<NavigationProp>()
   const closeAllActiveElements = useCloseAllActiveElements()
-  const {showLoggedOut} = useLoggedOutView()
 
   useAuxClick()
 
@@ -42,8 +32,6 @@ function ShellInner() {
     return unsubscribe
   }, [navigator, closeAllActiveElements])
 
-  const showBottomBar = isMobile && !onboardingState.isActive
-  const showSideNavs = !isMobile && !onboardingState.isActive && !showLoggedOut
   return (
     <View style={[s.hContentRegion, {overflow: 'hidden'}]}>
       <View style={s.hContentRegion}>
@@ -51,22 +39,9 @@ function ShellInner() {
           <FlatNavigator />
         </ErrorBoundary>
       </View>
-
-      {showSideNavs && (
-        <>
-          <DesktopLeftNav />
-          <DesktopRightNav />
-        </>
-      )}
-
       <Composer winHeight={0} />
-
-      {showBottomBar && <BottomBarWeb />}
-
       <ModalsContainer />
-
       <Lightbox />
-
       {!isDesktop && isDrawerOpen && (
         <TouchableOpacity
           onPress={() => setDrawerOpen(false)}