add banner nux
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
+1
-1
@@ -75,7 +75,7 @@
|
||||
"@atproto/api": "^0.18.4",
|
||||
"@bitdrift/react-native": "^0.6.8",
|
||||
"@braintree/sanitize-url": "^6.0.2",
|
||||
"@bsky.app/alf": "^0.1.5",
|
||||
"@bsky.app/alf": "^0.1.6",
|
||||
"@bsky.app/react-native-mmkv": "2.12.5",
|
||||
"@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet",
|
||||
"@emoji-mart/react": "^1.1.1",
|
||||
|
||||
@@ -38,7 +38,7 @@ export function Outer({
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
noBottomBorder?: boolean
|
||||
headerRef?: React.MutableRefObject<View | null>
|
||||
headerRef?: React.RefObject<View | null>
|
||||
sticky?: boolean
|
||||
}) {
|
||||
const t = useTheme()
|
||||
@@ -183,7 +183,7 @@ export function TitleText({
|
||||
<Text
|
||||
style={[
|
||||
a.text_lg,
|
||||
a.font_bold,
|
||||
a.font_semi_bold,
|
||||
a.leading_tight,
|
||||
isIOS && align === 'platform' && a.text_center,
|
||||
gtMobile && a.text_xl,
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
import {useMemo} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import Animated, {FadeOut} from 'react-native-reanimated'
|
||||
import {Image} from 'expo-image'
|
||||
import {LinearGradient} from 'expo-linear-gradient'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {HITSLOP_10} from '#/lib/constants'
|
||||
import {isWeb} from '#/platform/detection'
|
||||
import {Nux, useNux, useSaveNux} from '#/state/queries/nuxs'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Button} from '#/components/Button'
|
||||
import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {Link} from '../Link'
|
||||
|
||||
export function FindContactsBannerNUX() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {visible, close} = useInternalState()
|
||||
|
||||
if (!visible) return null
|
||||
|
||||
return (
|
||||
<Animated.View
|
||||
style={[a.w_full, a.p_lg, a.border_b, t.atoms.border_contrast_low]}
|
||||
exiting={FadeOut.duration(150)}>
|
||||
<View style={a.w_full}>
|
||||
<Link
|
||||
to={{screen: 'FindContactsFlow'}}
|
||||
label={_(msg`Import contacts to find your friends`)}
|
||||
style={[
|
||||
a.w_full,
|
||||
a.rounded_xl,
|
||||
a.curve_continuous,
|
||||
a.overflow_hidden,
|
||||
]}>
|
||||
<LinearGradient
|
||||
colors={[t.palette.primary_200, t.palette.primary_50]}
|
||||
start={{x: 0, y: 0.5}}
|
||||
end={{x: 1, y: 0.5}}
|
||||
style={[
|
||||
a.w_full,
|
||||
a.h_full,
|
||||
a.flex_row,
|
||||
a.align_center,
|
||||
a.gap_lg,
|
||||
a.pl_lg,
|
||||
]}>
|
||||
<Image
|
||||
source={require('../../../assets/images/find_friends_illustration_small.webp')}
|
||||
accessibilityIgnoresInvertColors={false}
|
||||
style={[
|
||||
{height: 70, aspectRatio: 573 / 286},
|
||||
a.self_end,
|
||||
a.mt_sm,
|
||||
]}
|
||||
/>
|
||||
<View style={[a.flex_1, a.justify_center, a.py_xl, a.pr_5xl]}>
|
||||
<Text
|
||||
style={[
|
||||
a.text_md,
|
||||
a.font_bold,
|
||||
{color: t.palette.primary_900},
|
||||
]}>
|
||||
<Trans>Import contacts to find your friends</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
</LinearGradient>
|
||||
</Link>
|
||||
<Button
|
||||
label={_(msg`Dismiss banner`)}
|
||||
hitSlop={HITSLOP_10}
|
||||
onPress={close}
|
||||
style={[a.absolute, {top: 14, right: 14}]}
|
||||
hoverStyle={[a.bg_transparent, {opacity: 0.5}]}>
|
||||
<XIcon size="xs" style={[t.atoms.text_contrast_low]} />
|
||||
</Button>
|
||||
</View>
|
||||
</Animated.View>
|
||||
)
|
||||
}
|
||||
function useInternalState() {
|
||||
const {nux} = useNux(Nux.FindContactsDismissibleBanner)
|
||||
const {mutate: save, variables} = useSaveNux()
|
||||
const hidden = !!variables
|
||||
|
||||
const visible = useMemo(() => {
|
||||
if (isWeb) return false
|
||||
if (hidden) return false
|
||||
if (nux && nux.completed) return false
|
||||
return true
|
||||
}, [hidden, nux])
|
||||
|
||||
const close = () => {
|
||||
save({
|
||||
id: Nux.FindContactsDismissibleBanner,
|
||||
completed: true,
|
||||
data: undefined,
|
||||
})
|
||||
}
|
||||
|
||||
return {visible, close}
|
||||
}
|
||||
@@ -10,6 +10,8 @@ export enum Nux {
|
||||
AgeAssuranceDismissibleNotice = 'AgeAssuranceDismissibleNotice',
|
||||
AgeAssuranceDismissibleFeedBanner = 'AgeAssuranceDismissibleFeedBanner',
|
||||
BookmarksAnnouncement = 'BookmarksAnnouncement',
|
||||
FindContactsAnnouncement = 'FindContactsAnnouncement',
|
||||
FindContactsDismissibleBanner = 'FindContactsDismissibleBanner',
|
||||
|
||||
/*
|
||||
* Blocking announcements. New IDs are required for each new announcement.
|
||||
@@ -52,6 +54,10 @@ export type AppNux = BaseNux<
|
||||
id: Nux.BookmarksAnnouncement
|
||||
data: undefined
|
||||
}
|
||||
| {
|
||||
id: Nux.FindContactsDismissibleBanner
|
||||
data: undefined
|
||||
}
|
||||
>
|
||||
|
||||
export const NuxSchemas: Record<Nux, zod.ZodObject<any> | undefined> = {
|
||||
@@ -63,4 +69,6 @@ export const NuxSchemas: Record<Nux, zod.ZodObject<any> | undefined> = {
|
||||
[Nux.AgeAssuranceDismissibleFeedBanner]: undefined,
|
||||
[Nux.PolicyUpdate202508]: undefined,
|
||||
[Nux.BookmarksAnnouncement]: undefined,
|
||||
[Nux.FindContactsAnnouncement]: undefined,
|
||||
[Nux.FindContactsDismissibleBanner]: undefined,
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {isWeb} from '#/platform/detection'
|
||||
import {useProfileFollowsQuery} from '#/state/queries/profile-follows'
|
||||
import {useResolveDidQuery} from '#/state/queries/resolve-uri'
|
||||
import {useSession} from '#/state/session'
|
||||
import {FindContactsBannerNUX} from '#/components/contacts/FindContactsBannerNUX'
|
||||
import {PeopleRemove2_Stroke1_Corner0_Rounded as PeopleRemoveIcon} from '#/components/icons/PeopleRemove2'
|
||||
import {ListFooter, ListMaybePlaceholder} from '#/components/Lists'
|
||||
import {List} from '../util/List'
|
||||
@@ -208,6 +209,7 @@ export function ProfileFollows({name}: {name: string}) {
|
||||
onEndReached={onEndReached}
|
||||
onEndReachedThreshold={4}
|
||||
onItemSeen={onItemSeen}
|
||||
ListHeaderComponent={<FindContactsBannerNUX />}
|
||||
ListFooterComponent={
|
||||
<ListFooter
|
||||
isFetchingNextPage={isFetchingNextPage}
|
||||
|
||||
@@ -3739,10 +3739,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz#923ca57e173c6b232bbbb07347b1be982f03e783"
|
||||
integrity sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==
|
||||
|
||||
"@bsky.app/alf@^0.1.5":
|
||||
version "0.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@bsky.app/alf/-/alf-0.1.5.tgz#8de3e128a3a490625fa24dae89f8febfe4a668b2"
|
||||
integrity sha512-1FGsLTUxv4UpbO3tW/oXIEzR8If/FPkFwWkTOBvpcA9cfR73QZiXXitUojCZbiXEIl0WiL+8j3zHjpNaaxiOAA==
|
||||
"@bsky.app/alf@^0.1.6":
|
||||
version "0.1.6"
|
||||
resolved "https://registry.yarnpkg.com/@bsky.app/alf/-/alf-0.1.6.tgz#256dac988702f076b98f1963c9d594141bc74a10"
|
||||
integrity sha512-8DdAOP+qRVgme+5WwqhxU20qzHXvEkEzr60SIBvDEVblCkyEiPZ36YznbpbmpT23qXbfbUFf9mb5IXYJqd8ELQ==
|
||||
dependencies:
|
||||
react-responsive "^10.0.1"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user