Invite friends: wire followers banner to find-friends settings, polish
- Add promo banner illustration (assets/images/invite_friends_promo_banner.webp) and replace the empty placeholder box in FollowersPromoBanner. - Redirect the followers empty-state banner to the Find and Invite Friends settings screen instead of opening the share sheet, gated to mirror that screen's availability (native, geolocation allowlist, feature flag) so we don't promote contact import where the settings entry is hidden. - Drop the now-dead invite dialog mount/control from ProfileFollowers and update the banner a11y copy to match the new destination. - Scanner: collapse the unused error-message state to a boolean (the overlay renders its own localized copy).
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
@@ -25,7 +25,7 @@ export function InviteScannerScreen() {
|
||||
const insets = useSafeAreaInsets()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const [permission, requestPermission] = useCameraPermissions()
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [showError, setShowError] = useState(false)
|
||||
const [scannerEnabled, setScannerEnabled] = useState(true)
|
||||
|
||||
const onClose = useCallback(() => {
|
||||
@@ -44,13 +44,7 @@ export function InviteScannerScreen() {
|
||||
)
|
||||
if (!profileMatch) {
|
||||
setScannerEnabled(false)
|
||||
setError(
|
||||
l({
|
||||
message: 'Profile not found',
|
||||
comment:
|
||||
'Error shown when a scanned QR code is not a valid Bluesky profile URL',
|
||||
}),
|
||||
)
|
||||
setShowError(true)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -58,11 +52,11 @@ export function InviteScannerScreen() {
|
||||
const handle = profileMatch[1]
|
||||
navigation.replace('Profile', {name: handle})
|
||||
},
|
||||
[scannerEnabled, navigation, l],
|
||||
[scannerEnabled, navigation],
|
||||
)
|
||||
|
||||
const onRetry = useCallback(() => {
|
||||
setError(null)
|
||||
setShowError(false)
|
||||
setScannerEnabled(true)
|
||||
}, [])
|
||||
|
||||
@@ -165,7 +159,7 @@ export function InviteScannerScreen() {
|
||||
</View>
|
||||
|
||||
{/* Error overlay shown when scanned QR isn't a valid profile URL */}
|
||||
{error && (
|
||||
{showError && (
|
||||
<View
|
||||
style={{
|
||||
position: 'absolute',
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {Pressable, View} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
@@ -18,8 +19,8 @@ export function FollowersPromoBanner({
|
||||
<View style={[a.px_lg, a.pt_md]}>
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={l`Invite friends`}
|
||||
accessibilityHint={l`Opens the invite friends sheet to share your profile`}
|
||||
accessibilityLabel={l`Find and invite friends`}
|
||||
accessibilityHint={l`Opens the find and invite friends settings`}
|
||||
onPress={onPress}
|
||||
style={({pressed}) => [
|
||||
a.flex_row,
|
||||
@@ -34,14 +35,11 @@ export function FollowersPromoBanner({
|
||||
opacity: pressed ? 0.85 : 1,
|
||||
},
|
||||
]}>
|
||||
<View
|
||||
style={{
|
||||
width: 126,
|
||||
height: 64,
|
||||
marginRight: 16,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
<Image
|
||||
accessibilityIgnoresInvertColors
|
||||
source={require('../../../../assets/images/invite_friends_promo_banner.webp')}
|
||||
style={{width: 126, height: 64, marginRight: 16}}
|
||||
contentFit="contain"
|
||||
/>
|
||||
<Text
|
||||
style={[
|
||||
|
||||
@@ -5,19 +5,19 @@ import {useLingui} from '@lingui/react'
|
||||
import {useNavigation} from '@react-navigation/native'
|
||||
|
||||
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
|
||||
import {type NavigationProp} from '#/lib/routes/types'
|
||||
import {cleanError} from '#/lib/strings/errors'
|
||||
import {logger} from '#/logger'
|
||||
import {useProfileFollowersQuery} from '#/state/queries/profile-followers'
|
||||
import {useResolveDidQuery} from '#/state/queries/resolve-uri'
|
||||
import {useSession} from '#/state/session'
|
||||
import {useDialogControl} from '#/components/Dialog'
|
||||
import {useIsFindContactsFeatureEnabledBasedOnGeolocation} from '#/components/contacts/country-allowlist'
|
||||
import {PeopleRemove2_Stroke1_Corner0_Rounded as PeopleRemoveIcon} from '#/components/icons/PeopleRemove2'
|
||||
import {ListFooter, ListMaybePlaceholder} from '#/components/Lists'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {IS_NATIVE} from '#/env'
|
||||
import {
|
||||
FollowersPromoBanner,
|
||||
InviteFriendsDialog,
|
||||
useFollowersPromoDismissed,
|
||||
} from '#/features/inviteFriends'
|
||||
import {List} from '../util/List'
|
||||
@@ -50,7 +50,7 @@ function keyExtractor(item: ActorDefs.ProfileViewBasic) {
|
||||
export function ProfileFollowers({name}: {name: string}) {
|
||||
const {_} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const navigation = useNavigation()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const initialNumToRender = useInitialNumToRender()
|
||||
const {currentAccount} = useSession()
|
||||
|
||||
@@ -165,14 +165,18 @@ export function ProfileFollowers({name}: {name: string}) {
|
||||
[ax, followers, resolvedDid],
|
||||
)
|
||||
|
||||
const inviteFriendsControl = useDialogControl()
|
||||
const [followersPromoDismissed, setFollowersPromoDismissed] =
|
||||
useFollowersPromoDismissed()
|
||||
// Native-only: the invite-friends sheet is a no-op on web, so the banner
|
||||
// would open nothing. Gate it to avoid a dead promo on web.
|
||||
const findContactsEnabled = useIsFindContactsFeatureEnabledBasedOnGeolocation()
|
||||
// The banner deep-links into the Find and Invite Friends settings screen, so
|
||||
// mirror that screen's availability gates: native-only, allowed in the user's
|
||||
// region (geolocation allowlist), and not disabled by the feature flag. This
|
||||
// avoids promoting contact import where the settings entry itself is hidden.
|
||||
const showFollowersPromo =
|
||||
IS_NATIVE &&
|
||||
isMe &&
|
||||
findContactsEnabled &&
|
||||
!ax.features.enabled(ax.features.ImportContactsSettingsDisable) &&
|
||||
!followersPromoDismissed &&
|
||||
followers.length < 1 &&
|
||||
!isDidLoading &&
|
||||
@@ -184,7 +188,7 @@ export function ProfileFollowers({name}: {name: string}) {
|
||||
<>
|
||||
{showFollowersPromo && (
|
||||
<FollowersPromoBanner
|
||||
onPress={() => inviteFriendsControl.open()}
|
||||
onPress={() => navigation.navigate('FindContactsSettings')}
|
||||
onDismiss={() => setFollowersPromoDismissed(true)}
|
||||
/>
|
||||
)}
|
||||
@@ -210,9 +214,6 @@ export function ProfileFollowers({name}: {name: string}) {
|
||||
onPress: () => navigation.goBack(),
|
||||
}}
|
||||
/>
|
||||
{showFollowersPromo && (
|
||||
<InviteFriendsDialog control={inviteFriendsControl} />
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user