Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

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

Some brand, some pwi (#2212)

* Add logo to left nav in logged out

* Protect last routes

* Hide links in left nav, hide nav

* Replace bottom bar for pwi

* Remove same links from drawer

* Hide reply prompt

* Allow search

authored by

Eric Bailey and committed by
GitHub
1111108e 7897dd24

+296 -154
+7 -3
src/Navigation.tsx
··· 292 292 animationDuration: 250, 293 293 contentStyle, 294 294 }}> 295 - <HomeTab.Screen name="Home" getComponent={() => HomeScreen} /> 295 + <HomeTab.Screen 296 + name="Home" 297 + getComponent={() => HomeScreen} 298 + options={{requireAuth: true}} 299 + /> 296 300 {commonScreens(HomeTab)} 297 301 </HomeTab.Navigator> 298 302 ) ··· 402 406 <Flat.Screen 403 407 name="Home" 404 408 getComponent={() => HomeScreen} 405 - options={{title: title('Home')}} 409 + options={{title: title('Home'), requireAuth: true}} 406 410 /> 407 411 <Flat.Screen 408 412 name="Search" ··· 412 416 <Flat.Screen 413 417 name="Feeds" 414 418 getComponent={() => FeedsScreen} 415 - options={{title: title('Feeds')}} 419 + options={{title: title('Feeds'), requireAuth: true}} 416 420 /> 417 421 <Flat.Screen 418 422 name="Notifications"
+3 -1
src/view/screens/PostThread.tsx
··· 24 24 import {ErrorMessage} from '../com/util/error/ErrorMessage' 25 25 import {CenteredView} from '../com/util/Views' 26 26 import {useComposerControls} from '#/state/shell/composer' 27 + import {useSession} from '#/state/session' 27 28 28 29 type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostThread'> 29 30 export function PostThreadScreen({route}: Props) { 30 31 const queryClient = useQueryClient() 31 32 const {_} = useLingui() 33 + const {hasSession} = useSession() 32 34 const {fabMinimalShellTransform} = useMinimalShellMode() 33 35 const setMinimalShellMode = useSetMinimalShellMode() 34 36 const {openComposer} = useComposerControls() ··· 89 91 /> 90 92 )} 91 93 </View> 92 - {isMobile && canReply && ( 94 + {isMobile && canReply && hasSession && ( 93 95 <Animated.View 94 96 style={[ 95 97 styles.prompt,
+11 -11
src/view/shell/Drawer.tsx
··· 221 221 <NavSignupCard /> 222 222 )} 223 223 224 - {hasSession && <InviteCodes />} 225 - {hasSession && <View style={{height: 10}} />} 226 - <SearchMenuItem isActive={isAtSearch} onPress={onPressSearch} /> 227 - <HomeMenuItem isActive={isAtHome} onPress={onPressHome} /> 228 - {hasSession && ( 229 - <NotificationsMenuItem 230 - isActive={isAtNotifications} 231 - onPress={onPressNotifications} 232 - /> 233 - )} 234 - {hasSession && ( 224 + {hasSession ? ( 235 225 <> 226 + <InviteCodes /> 227 + <View style={{height: 10}} /> 228 + <SearchMenuItem isActive={isAtSearch} onPress={onPressSearch} /> 229 + <HomeMenuItem isActive={isAtHome} onPress={onPressHome} /> 230 + <NotificationsMenuItem 231 + isActive={isAtNotifications} 232 + onPress={onPressNotifications} 233 + /> 236 234 <FeedsMenuItem isActive={isAtFeeds} onPress={onPressMyFeeds} /> 237 235 <ListsMenuItem onPress={onPressLists} /> 238 236 <ModerationMenuItem onPress={onPressModeration} /> ··· 242 240 /> 243 241 <SettingsMenuItem onPress={onPressSettings} /> 244 242 </> 243 + ) : ( 244 + <SearchMenuItem isActive={isAtSearch} onPress={onPressSearch} /> 245 245 )} 246 246 247 247 <View style={styles.smallSpacer} />
+4 -4
src/view/shell/NavSignupCard.tsx
··· 5 5 6 6 import {s} from 'lib/styles' 7 7 import {usePalette} from 'lib/hooks/usePalette' 8 - import {DefaultAvatar} from '#/view/com/util/UserAvatar' 9 8 import {Text} from '#/view/com/util/text/Text' 10 9 import {Button} from '#/view/com/util/forms/Button' 11 10 import {useLoggedOutViewControls} from '#/state/shell/logged-out' 12 11 import {useCloseAllActiveElements} from '#/state/util' 12 + import {Logo} from '#/view/icons/Logo' 13 13 14 14 let NavSignupCard = ({}: {}): React.ReactNode => { 15 15 const {_} = useLingui() ··· 35 35 paddingTop: 6, 36 36 marginBottom: 24, 37 37 }}> 38 - <DefaultAvatar type="user" size={48} /> 38 + <Logo width={48} /> 39 39 40 - <View style={{paddingTop: 12}}> 41 - <Text type="md" style={[pal.text, s.bold]}> 40 + <View style={{paddingTop: 18}}> 41 + <Text type="md-bold" style={[pal.text]}> 42 42 <Trans>Sign up or sign in to join the conversation</Trans> 43 43 </Text> 44 44 </View>
+108 -47
src/view/shell/bottom-bar/BottomBar.tsx
··· 23 23 import {useNavigationTabState} from 'lib/hooks/useNavigationTabState' 24 24 import {UserAvatar} from 'view/com/util/UserAvatar' 25 25 import {useLingui} from '@lingui/react' 26 - import {msg} from '@lingui/macro' 26 + import {msg, Trans} from '@lingui/macro' 27 27 import {useModalControls} from '#/state/modals' 28 28 import {useShellLayout} from '#/state/shell/shell-layout' 29 29 import {useUnreadNotifications} from '#/state/queries/notifications/unread' 30 30 import {emitSoftReset} from '#/state/events' 31 31 import {useSession} from '#/state/session' 32 32 import {useProfileQuery} from '#/state/queries/profile' 33 + import {useLoggedOutViewControls} from '#/state/shell/logged-out' 34 + import {useCloseAllActiveElements} from '#/state/util' 35 + import {Button} from '#/view/com/util/forms/Button' 36 + import {s} from 'lib/styles' 37 + import {Logo} from '#/view/icons/Logo' 38 + import {Logotype} from '#/view/icons/Logotype' 33 39 34 40 type TabOptions = 'Home' | 'Search' | 'Notifications' | 'MyProfile' | 'Feeds' 35 41 ··· 46 52 const numUnreadNotifications = useUnreadNotifications() 47 53 const {footerMinimalShellTransform} = useMinimalShellMode() 48 54 const {data: profile} = useProfileQuery({did: currentAccount?.did}) 55 + const {requestSwitchToAccount} = useLoggedOutViewControls() 56 + const closeAllActiveElements = useCloseAllActiveElements() 57 + 58 + const showSignIn = React.useCallback(() => { 59 + closeAllActiveElements() 60 + requestSwitchToAccount({requestedAccount: 'none'}) 61 + }, [requestSwitchToAccount, closeAllActiveElements]) 62 + 63 + const showCreateAccount = React.useCallback(() => { 64 + closeAllActiveElements() 65 + requestSwitchToAccount({requestedAccount: 'new'}) 66 + // setShowLoggedOut(true) 67 + }, [requestSwitchToAccount, closeAllActiveElements]) 49 68 50 69 const onPressTab = React.useCallback( 51 70 (tab: TabOptions) => { ··· 94 113 onLayout={e => { 95 114 footerHeight.value = e.nativeEvent.layout.height 96 115 }}> 97 - <Btn 98 - testID="bottomBarHomeBtn" 99 - icon={ 100 - isAtHome ? ( 101 - <HomeIconSolid 102 - strokeWidth={4} 103 - size={24} 104 - style={[styles.ctrlIcon, pal.text, styles.homeIcon]} 105 - /> 106 - ) : ( 107 - <HomeIcon 108 - strokeWidth={4} 109 - size={24} 110 - style={[styles.ctrlIcon, pal.text, styles.homeIcon]} 111 - /> 112 - ) 113 - } 114 - onPress={onPressHome} 115 - accessibilityRole="tab" 116 - accessibilityLabel={_(msg`Home`)} 117 - accessibilityHint="" 118 - /> 119 - <Btn 120 - testID="bottomBarSearchBtn" 121 - icon={ 122 - isAtSearch ? ( 123 - <MagnifyingGlassIcon2Solid 124 - size={25} 125 - style={[styles.ctrlIcon, pal.text, styles.searchIcon]} 126 - strokeWidth={1.8} 127 - /> 128 - ) : ( 129 - <MagnifyingGlassIcon2 130 - size={25} 131 - style={[styles.ctrlIcon, pal.text, styles.searchIcon]} 132 - strokeWidth={1.8} 133 - /> 134 - ) 135 - } 136 - onPress={onPressSearch} 137 - accessibilityRole="search" 138 - accessibilityLabel={_(msg`Search`)} 139 - accessibilityHint="" 140 - /> 141 - 142 - {hasSession && ( 116 + {hasSession ? ( 143 117 <> 144 118 <Btn 119 + testID="bottomBarHomeBtn" 120 + icon={ 121 + isAtHome ? ( 122 + <HomeIconSolid 123 + strokeWidth={4} 124 + size={24} 125 + style={[styles.ctrlIcon, pal.text, styles.homeIcon]} 126 + /> 127 + ) : ( 128 + <HomeIcon 129 + strokeWidth={4} 130 + size={24} 131 + style={[styles.ctrlIcon, pal.text, styles.homeIcon]} 132 + /> 133 + ) 134 + } 135 + onPress={onPressHome} 136 + accessibilityRole="tab" 137 + accessibilityLabel={_(msg`Home`)} 138 + accessibilityHint="" 139 + /> 140 + <Btn 141 + testID="bottomBarSearchBtn" 142 + icon={ 143 + isAtSearch ? ( 144 + <MagnifyingGlassIcon2Solid 145 + size={25} 146 + style={[styles.ctrlIcon, pal.text, styles.searchIcon]} 147 + strokeWidth={1.8} 148 + /> 149 + ) : ( 150 + <MagnifyingGlassIcon2 151 + size={25} 152 + style={[styles.ctrlIcon, pal.text, styles.searchIcon]} 153 + strokeWidth={1.8} 154 + /> 155 + ) 156 + } 157 + onPress={onPressSearch} 158 + accessibilityRole="search" 159 + accessibilityLabel={_(msg`Search`)} 160 + accessibilityHint="" 161 + /> 162 + <Btn 145 163 testID="bottomBarFeedsBtn" 146 164 icon={ 147 165 isAtFeeds ? ( ··· 229 247 accessibilityLabel={_(msg`Profile`)} 230 248 accessibilityHint="" 231 249 /> 250 + </> 251 + ) : ( 252 + <> 253 + <View 254 + style={{ 255 + width: '100%', 256 + flexDirection: 'row', 257 + alignItems: 'center', 258 + justifyContent: 'space-between', 259 + paddingTop: 14, 260 + paddingBottom: 2, 261 + paddingLeft: 14, 262 + paddingRight: 6, 263 + gap: 8, 264 + }}> 265 + <View style={{flexDirection: 'row', alignItems: 'center', gap: 8}}> 266 + <Logo width={28} /> 267 + <View style={{paddingTop: 4}}> 268 + <Logotype width={80} /> 269 + </View> 270 + </View> 271 + 272 + <View style={{flexDirection: 'row', alignItems: 'center', gap: 4}}> 273 + <Button 274 + onPress={showCreateAccount} 275 + accessibilityHint={_(msg`Sign up`)} 276 + accessibilityLabel={_(msg`Sign up`)}> 277 + <Text type="md" style={[{color: 'white'}, s.bold]}> 278 + <Trans>Sign up</Trans> 279 + </Text> 280 + </Button> 281 + 282 + <Button 283 + type="default" 284 + onPress={showSignIn} 285 + accessibilityHint={_(msg`Sign in`)} 286 + accessibilityLabel={_(msg`Sign in`)}> 287 + <Text type="md" style={[pal.text, s.bold]}> 288 + <Trans>Sign in</Trans> 289 + </Text> 290 + </Button> 291 + </View> 292 + </View> 232 293 </> 233 294 )} 234 295 </Animated.View>
+128 -57
src/view/shell/bottom-bar/BottomBarWeb.tsx
··· 3 3 import {useNavigationState} from '@react-navigation/native' 4 4 import Animated from 'react-native-reanimated' 5 5 import {useSafeAreaInsets} from 'react-native-safe-area-context' 6 + import {View} from 'react-native' 7 + import {msg, Trans} from '@lingui/macro' 8 + import {useLingui} from '@lingui/react' 6 9 import {getCurrentRoute, isTab} from 'lib/routes/helpers' 7 10 import {styles} from './BottomBarStyles' 8 11 import {clamp} from 'lib/numbers' ··· 22 25 import {makeProfileLink} from 'lib/routes/links' 23 26 import {CommonNavigatorParams} from 'lib/routes/types' 24 27 import {useSession} from '#/state/session' 28 + import {useLoggedOutViewControls} from '#/state/shell/logged-out' 29 + import {useCloseAllActiveElements} from '#/state/util' 30 + import {Button} from '#/view/com/util/forms/Button' 31 + import {Text} from '#/view/com/util/text/Text' 32 + import {s} from 'lib/styles' 33 + import {Logo} from '#/view/icons/Logo' 34 + import {Logotype} from '#/view/icons/Logotype' 25 35 26 36 export function BottomBarWeb() { 37 + const {_} = useLingui() 27 38 const {hasSession, currentAccount} = useSession() 28 39 const pal = usePalette('default') 29 40 const safeAreaInsets = useSafeAreaInsets() 30 41 const {footerMinimalShellTransform} = useMinimalShellMode() 42 + const {requestSwitchToAccount} = useLoggedOutViewControls() 43 + const closeAllActiveElements = useCloseAllActiveElements() 44 + 45 + const showSignIn = React.useCallback(() => { 46 + closeAllActiveElements() 47 + requestSwitchToAccount({requestedAccount: 'none'}) 48 + }, [requestSwitchToAccount, closeAllActiveElements]) 49 + 50 + const showCreateAccount = React.useCallback(() => { 51 + closeAllActiveElements() 52 + requestSwitchToAccount({requestedAccount: 'new'}) 53 + // setShowLoggedOut(true) 54 + }, [requestSwitchToAccount, closeAllActiveElements]) 31 55 32 56 return ( 33 57 <Animated.View ··· 38 62 {paddingBottom: clamp(safeAreaInsets.bottom, 15, 30)}, 39 63 footerMinimalShellTransform, 40 64 ]}> 41 - <NavItem routeName="Home" href="/"> 42 - {({isActive}) => { 43 - const Icon = isActive ? HomeIconSolid : HomeIcon 44 - return ( 45 - <Icon 46 - strokeWidth={4} 47 - size={24} 48 - style={[styles.ctrlIcon, pal.text, styles.homeIcon]} 49 - /> 50 - ) 51 - }} 52 - </NavItem> 53 - <NavItem routeName="Search" href="/search"> 54 - {({isActive}) => { 55 - const Icon = isActive 56 - ? MagnifyingGlassIcon2Solid 57 - : MagnifyingGlassIcon2 58 - return ( 59 - <Icon 60 - size={25} 61 - style={[styles.ctrlIcon, pal.text, styles.searchIcon]} 62 - strokeWidth={1.8} 63 - /> 64 - ) 65 - }} 66 - </NavItem> 67 - 68 - {hasSession && ( 65 + {hasSession ? ( 69 66 <> 70 - <NavItem routeName="Feeds" href="/feeds"> 67 + <NavItem routeName="Home" href="/"> 71 68 {({isActive}) => { 72 - return ( 73 - <HashtagIcon 74 - size={22} 75 - style={[styles.ctrlIcon, pal.text, styles.feedsIcon]} 76 - strokeWidth={isActive ? 4 : 2.5} 77 - /> 78 - ) 79 - }} 80 - </NavItem> 81 - <NavItem routeName="Notifications" href="/notifications"> 82 - {({isActive}) => { 83 - const Icon = isActive ? BellIconSolid : BellIcon 69 + const Icon = isActive ? HomeIconSolid : HomeIcon 84 70 return ( 85 71 <Icon 72 + strokeWidth={4} 86 73 size={24} 87 - strokeWidth={1.9} 88 - style={[styles.ctrlIcon, pal.text, styles.bellIcon]} 74 + style={[styles.ctrlIcon, pal.text, styles.homeIcon]} 89 75 /> 90 76 ) 91 77 }} 92 78 </NavItem> 93 - <NavItem 94 - routeName="Profile" 95 - href={ 96 - currentAccount 97 - ? makeProfileLink({ 98 - did: currentAccount.did, 99 - handle: currentAccount.handle, 100 - }) 101 - : '/' 102 - }> 79 + <NavItem routeName="Search" href="/search"> 103 80 {({isActive}) => { 104 - const Icon = isActive ? UserIconSolid : UserIcon 81 + const Icon = isActive 82 + ? MagnifyingGlassIcon2Solid 83 + : MagnifyingGlassIcon2 105 84 return ( 106 85 <Icon 107 - size={28} 108 - strokeWidth={1.5} 109 - style={[styles.ctrlIcon, pal.text, styles.profileIcon]} 86 + size={25} 87 + style={[styles.ctrlIcon, pal.text, styles.searchIcon]} 88 + strokeWidth={1.8} 110 89 /> 111 90 ) 112 91 }} 113 92 </NavItem> 93 + 94 + {hasSession && ( 95 + <> 96 + <NavItem routeName="Feeds" href="/feeds"> 97 + {({isActive}) => { 98 + return ( 99 + <HashtagIcon 100 + size={22} 101 + style={[styles.ctrlIcon, pal.text, styles.feedsIcon]} 102 + strokeWidth={isActive ? 4 : 2.5} 103 + /> 104 + ) 105 + }} 106 + </NavItem> 107 + <NavItem routeName="Notifications" href="/notifications"> 108 + {({isActive}) => { 109 + const Icon = isActive ? BellIconSolid : BellIcon 110 + return ( 111 + <Icon 112 + size={24} 113 + strokeWidth={1.9} 114 + style={[styles.ctrlIcon, pal.text, styles.bellIcon]} 115 + /> 116 + ) 117 + }} 118 + </NavItem> 119 + <NavItem 120 + routeName="Profile" 121 + href={ 122 + currentAccount 123 + ? makeProfileLink({ 124 + did: currentAccount.did, 125 + handle: currentAccount.handle, 126 + }) 127 + : '/' 128 + }> 129 + {({isActive}) => { 130 + const Icon = isActive ? UserIconSolid : UserIcon 131 + return ( 132 + <Icon 133 + size={28} 134 + strokeWidth={1.5} 135 + style={[styles.ctrlIcon, pal.text, styles.profileIcon]} 136 + /> 137 + ) 138 + }} 139 + </NavItem> 140 + </> 141 + )} 142 + </> 143 + ) : ( 144 + <> 145 + <View 146 + style={{ 147 + width: '100%', 148 + flexDirection: 'row', 149 + alignItems: 'center', 150 + justifyContent: 'space-between', 151 + paddingTop: 14, 152 + paddingBottom: 2, 153 + paddingLeft: 14, 154 + paddingRight: 6, 155 + gap: 8, 156 + }}> 157 + <View style={{flexDirection: 'row', alignItems: 'center', gap: 12}}> 158 + <Logo width={32} /> 159 + <View style={{paddingTop: 4}}> 160 + <Logotype width={80} /> 161 + </View> 162 + </View> 163 + 164 + <View style={{flexDirection: 'row', alignItems: 'center', gap: 8}}> 165 + <Button 166 + onPress={showCreateAccount} 167 + accessibilityHint={_(msg`Sign up`)} 168 + accessibilityLabel={_(msg`Sign up`)}> 169 + <Text type="md" style={[{color: 'white'}, s.bold]}> 170 + <Trans>Sign up</Trans> 171 + </Text> 172 + </Button> 173 + 174 + <Button 175 + type="default" 176 + onPress={showSignIn} 177 + accessibilityHint={_(msg`Sign in`)} 178 + accessibilityLabel={_(msg`Sign in`)}> 179 + <Text type="md" style={[pal.text, s.bold]}> 180 + <Trans>Sign in</Trans> 181 + </Text> 182 + </Button> 183 + </View> 184 + </View> 114 185 </> 115 186 )} 116 187 </Animated.View>
+35 -31
src/view/shell/desktop/LeftNav.tsx
··· 266 266 const {isDesktop, isTablet} = useWebMediaQueries() 267 267 const numUnread = useUnreadNotifications() 268 268 269 + if (!hasSession && !isDesktop) { 270 + return null 271 + } 272 + 269 273 return ( 270 274 <View 271 275 style={[ ··· 282 286 </View> 283 287 ) : null} 284 288 285 - <BackBtn /> 289 + {hasSession && ( 290 + <> 291 + <BackBtn /> 286 292 287 - <NavItem 288 - href="/" 289 - icon={<HomeIcon size={isDesktop ? 24 : 28} style={pal.text} />} 290 - iconFilled={ 291 - <HomeIconSolid 292 - strokeWidth={4} 293 - size={isDesktop ? 24 : 28} 294 - style={pal.text} 295 - /> 296 - } 297 - label={_(msg`Home`)} 298 - /> 299 - <NavItem 300 - href="/search" 301 - icon={ 302 - <MagnifyingGlassIcon2 303 - strokeWidth={2} 304 - size={isDesktop ? 24 : 26} 305 - style={pal.text} 293 + <NavItem 294 + href="/" 295 + icon={<HomeIcon size={isDesktop ? 24 : 28} style={pal.text} />} 296 + iconFilled={ 297 + <HomeIconSolid 298 + strokeWidth={4} 299 + size={isDesktop ? 24 : 28} 300 + style={pal.text} 301 + /> 302 + } 303 + label={_(msg`Home`)} 306 304 /> 307 - } 308 - iconFilled={ 309 - <MagnifyingGlassIcon2Solid 310 - strokeWidth={2} 311 - size={isDesktop ? 24 : 26} 312 - style={pal.text} 305 + <NavItem 306 + href="/search" 307 + icon={ 308 + <MagnifyingGlassIcon2 309 + strokeWidth={2} 310 + size={isDesktop ? 24 : 26} 311 + style={pal.text} 312 + /> 313 + } 314 + iconFilled={ 315 + <MagnifyingGlassIcon2Solid 316 + strokeWidth={2} 317 + size={isDesktop ? 24 : 26} 318 + style={pal.text} 319 + /> 320 + } 321 + label={_(msg`Search`)} 313 322 /> 314 - } 315 - label={_(msg`Search`)} 316 - /> 317 - {hasSession && ( 318 - <> 319 323 <NavItem 320 324 href="/feeds" 321 325 icon={