PWI improvements (#3489)
* Enable home and feeds on the PWI * Add global SigninDialog to drive useRequireAuth() * Tweak desktop styles * Make the logo in leftnav PWI a clickable home link * Add label * Improve dialog on web * Fix query key * Go to home after signout from settings screen * Filter out feeds from the discover listing for logged out users which are known to break without auth * Update profile header follow/subscribe to give signin prompt * Show profile feeds tabs on pwi * Add language selector to account creation footer and pwi left nav desktop --------- Co-authored-by: dan <dan.abramov@gmail.com>
This commit is contained in:
parent
44039c68d6
commit
ec5c4929c1
23 changed files with 519 additions and 478 deletions
|
@ -1,52 +1,53 @@
|
|||
import React from 'react'
|
||||
import {
|
||||
ActivityIndicator,
|
||||
StyleSheet,
|
||||
View,
|
||||
type FlatList,
|
||||
Pressable,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||
import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
|
||||
import {ViewHeader} from 'view/com/util/ViewHeader'
|
||||
import {FAB} from 'view/com/util/fab/FAB'
|
||||
import {Link} from 'view/com/util/Link'
|
||||
import {NativeStackScreenProps, FeedsTabNavigatorParams} from 'lib/routes/types'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {ComposeIcon2, CogIcon, MagnifyingGlassIcon2} from 'lib/icons'
|
||||
import {s} from 'lib/styles'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {SearchInput, SearchInputRef} from 'view/com/util/forms/SearchInput'
|
||||
import {UserAvatar} from 'view/com/util/UserAvatar'
|
||||
import {
|
||||
LoadingPlaceholder,
|
||||
FeedFeedLoadingPlaceholder,
|
||||
} from 'view/com/util/LoadingPlaceholder'
|
||||
import {ErrorMessage} from 'view/com/util/error/ErrorMessage'
|
||||
import debounce from 'lodash.debounce'
|
||||
import {Text} from 'view/com/util/text/Text'
|
||||
import {List} from 'view/com/util/List'
|
||||
import {useFocusEffect} from '@react-navigation/native'
|
||||
import {FeedSourceCard} from 'view/com/feeds/FeedSourceCard'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useSetMinimalShellMode} from '#/state/shell'
|
||||
import {usePreferencesQuery} from '#/state/queries/preferences'
|
||||
import {useFocusEffect} from '@react-navigation/native'
|
||||
import debounce from 'lodash.debounce'
|
||||
|
||||
import {isNative, isWeb} from '#/platform/detection'
|
||||
import {
|
||||
getAvatarTypeFromUri,
|
||||
useFeedSourceInfoQuery,
|
||||
useGetPopularFeedsQuery,
|
||||
useSearchPopularFeedsMutation,
|
||||
getAvatarTypeFromUri,
|
||||
} from '#/state/queries/feed'
|
||||
import {cleanError} from 'lib/strings/errors'
|
||||
import {useComposerControls} from '#/state/shell/composer'
|
||||
import {usePreferencesQuery} from '#/state/queries/preferences'
|
||||
import {useSession} from '#/state/session'
|
||||
import {isNative, isWeb} from '#/platform/detection'
|
||||
import {useSetMinimalShellMode} from '#/state/shell'
|
||||
import {useComposerControls} from '#/state/shell/composer'
|
||||
import {HITSLOP_10} from 'lib/constants'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {CogIcon, ComposeIcon2, MagnifyingGlassIcon2} from 'lib/icons'
|
||||
import {FeedsTabNavigatorParams, NativeStackScreenProps} from 'lib/routes/types'
|
||||
import {cleanError} from 'lib/strings/errors'
|
||||
import {s} from 'lib/styles'
|
||||
import {FeedSourceCard} from 'view/com/feeds/FeedSourceCard'
|
||||
import {ErrorMessage} from 'view/com/util/error/ErrorMessage'
|
||||
import {FAB} from 'view/com/util/fab/FAB'
|
||||
import {SearchInput, SearchInputRef} from 'view/com/util/forms/SearchInput'
|
||||
import {Link} from 'view/com/util/Link'
|
||||
import {List} from 'view/com/util/List'
|
||||
import {
|
||||
FeedFeedLoadingPlaceholder,
|
||||
LoadingPlaceholder,
|
||||
} from 'view/com/util/LoadingPlaceholder'
|
||||
import {Text} from 'view/com/util/text/Text'
|
||||
import {UserAvatar} from 'view/com/util/UserAvatar'
|
||||
import {ViewHeader} from 'view/com/util/ViewHeader'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {IconCircle} from '#/components/IconCircle'
|
||||
import {ListSparkle_Stroke2_Corner0_Rounded} from '#/components/icons/ListSparkle'
|
||||
import {ListMagnifyingGlass_Stroke2_Corner0_Rounded} from '#/components/icons/ListMagnifyingGlass'
|
||||
import {ListSparkle_Stroke2_Corner0_Rounded} from '#/components/icons/ListSparkle'
|
||||
|
||||
type Props = NativeStackScreenProps<FeedsTabNavigatorParams, 'Feeds'>
|
||||
|
||||
|
@ -100,6 +101,22 @@ type FlatlistSlice =
|
|||
key: string
|
||||
}
|
||||
|
||||
// HACK
|
||||
// the protocol doesn't yet tell us which feeds are personalized
|
||||
// this list is used to filter out feed recommendations from logged out users
|
||||
// for the ones we know need it
|
||||
// -prf
|
||||
const KNOWN_AUTHED_ONLY_FEEDS = [
|
||||
'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/with-friends', // popular with friends, by bsky.app
|
||||
'at://did:plc:tenurhgjptubkk5zf5qhi3og/app.bsky.feed.generator/mutuals', // mutuals, by skyfeed
|
||||
'at://did:plc:tenurhgjptubkk5zf5qhi3og/app.bsky.feed.generator/only-posts', // only posts, by skyfeed
|
||||
'at://did:plc:wzsilnxf24ehtmmc3gssy5bu/app.bsky.feed.generator/mentions', // mentions, by flicknow
|
||||
'at://did:plc:q6gjnaw2blty4crticxkmujt/app.bsky.feed.generator/bangers', // my bangers, by jaz
|
||||
'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/mutuals', // mutuals, by bluesky
|
||||
'at://did:plc:q6gjnaw2blty4crticxkmujt/app.bsky.feed.generator/my-followers', // followers, by jaz
|
||||
'at://did:plc:vpkhqolt662uhesyj6nxm7ys/app.bsky.feed.generator/followpics', // the gram, by why
|
||||
]
|
||||
|
||||
export function FeedsScreen(_props: Props) {
|
||||
const pal = usePalette('default')
|
||||
const {openComposer} = useComposerControls()
|
||||
|
@ -299,7 +316,15 @@ export function FeedsScreen(_props: Props) {
|
|||
for (const page of popularFeeds.pages || []) {
|
||||
slices = slices.concat(
|
||||
page.feeds
|
||||
.filter(feed => !preferences?.feeds?.saved.includes(feed.uri))
|
||||
.filter(feed => {
|
||||
if (
|
||||
!hasSession &&
|
||||
KNOWN_AUTHED_ONLY_FEEDS.includes(feed.uri)
|
||||
) {
|
||||
return false
|
||||
}
|
||||
return !preferences?.feeds?.saved.includes(feed.uri)
|
||||
})
|
||||
.map(feed => ({
|
||||
key: `popularFeed:${feed.uri}`,
|
||||
type: 'popularFeed',
|
||||
|
|
|
@ -2,6 +2,7 @@ import React from 'react'
|
|||
import {ActivityIndicator, AppState, StyleSheet, View} from 'react-native'
|
||||
import {useFocusEffect} from '@react-navigation/native'
|
||||
|
||||
import {PROD_DEFAULT_FEED} from '#/lib/constants'
|
||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||
import {useSetTitle} from '#/lib/hooks/useSetTitle'
|
||||
import {logEvent, LogEvents, useGate} from '#/lib/statsig/statsig'
|
||||
|
@ -19,7 +20,6 @@ import {Pager, PagerRef, RenderTabBarFnProps} from 'view/com/pager/Pager'
|
|||
import {CustomFeedEmptyState} from 'view/com/posts/CustomFeedEmptyState'
|
||||
import {FollowingEmptyState} from 'view/com/posts/FollowingEmptyState'
|
||||
import {FollowingEndOfFeed} from 'view/com/posts/FollowingEndOfFeed'
|
||||
import {HomeLoggedOutCTA} from '../com/auth/HomeLoggedOutCTA'
|
||||
import {HomeHeader} from '../com/home/HomeHeader'
|
||||
|
||||
type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'>
|
||||
|
@ -231,7 +231,12 @@ function HomeScreenReady({
|
|||
onPageSelected={onPageSelected}
|
||||
onPageScrollStateChanged={onPageScrollStateChanged}
|
||||
renderTabBar={renderTabBar}>
|
||||
<HomeLoggedOutCTA />
|
||||
<FeedPage
|
||||
testID="customFeedPage"
|
||||
isPageFocused
|
||||
feed={`feedgen|${PROD_DEFAULT_FEED('whats-hot')}`}
|
||||
renderEmptyState={renderCustomFeedEmptyState}
|
||||
/>
|
||||
</Pager>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -184,8 +184,7 @@ function ProfileScreenLoaded({
|
|||
const showRepliesTab = hasSession
|
||||
const showMediaTab = !hasLabeler
|
||||
const showLikesTab = isMe
|
||||
const showFeedsTab =
|
||||
hasSession && (isMe || (profile.associated?.feedgens || 0) > 0)
|
||||
const showFeedsTab = isMe || (profile.associated?.feedgens || 0) > 0
|
||||
const showListsTab =
|
||||
hasSession && (isMe || (profile.associated?.lists || 0) > 0)
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ import {UserAvatar} from 'view/com/util/UserAvatar'
|
|||
import {ScrollView} from 'view/com/util/Views'
|
||||
import {useDialogControl} from '#/components/Dialog'
|
||||
import {BirthDateSettingsDialog} from '#/components/dialogs/BirthDateSettings'
|
||||
import {navigate, resetToTab} from '#/Navigation'
|
||||
import {ExportCarDialog} from './ExportCarDialog'
|
||||
|
||||
function SettingsAccountCard({account}: {account: SessionAccount}) {
|
||||
|
@ -104,7 +105,14 @@ function SettingsAccountCard({account}: {account: SessionAccount}) {
|
|||
<TouchableOpacity
|
||||
testID="signOutBtn"
|
||||
onPress={() => {
|
||||
logout('Settings')
|
||||
if (isNative) {
|
||||
logout('Settings')
|
||||
resetToTab('HomeTab')
|
||||
} else {
|
||||
navigate('Home').then(() => {
|
||||
logout('Settings')
|
||||
})
|
||||
}
|
||||
}}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={_(msg`Sign out`)}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue