add button + dialog
This commit is contained in:
@@ -0,0 +1,59 @@
|
|||||||
|
import {useCallback} from 'react'
|
||||||
|
import {msg, Trans} from '@lingui/macro'
|
||||||
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
|
import {useRequireEmailVerification} from '#/lib/hooks/useRequireEmailVerification'
|
||||||
|
import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name'
|
||||||
|
import {atoms as a} from '#/alf'
|
||||||
|
import {Button, ButtonIcon} from '#/components/Button'
|
||||||
|
import {useDialogControl} from '#/components/Dialog'
|
||||||
|
import type * as bsky from '#/types/bsky'
|
||||||
|
import {Bell_Stroke2_Corner0_Rounded as NotificationIcon} from '../icons/Bell'
|
||||||
|
import {SubscribeProfileDialog} from './SubscribeProfileDialog'
|
||||||
|
|
||||||
|
export function SubscribeProfileButton({
|
||||||
|
profile,
|
||||||
|
}: {
|
||||||
|
profile: bsky.profile.AnyProfileView
|
||||||
|
}) {
|
||||||
|
const {_} = useLingui()
|
||||||
|
const requireEmailVerification = useRequireEmailVerification()
|
||||||
|
const subscribeDialogControl = useDialogControl()
|
||||||
|
|
||||||
|
const onPress = useCallback(() => {
|
||||||
|
subscribeDialogControl.open()
|
||||||
|
}, [subscribeDialogControl])
|
||||||
|
|
||||||
|
const name = createSanitizedDisplayName(profile, true)
|
||||||
|
|
||||||
|
const wrappedOnPress = requireEmailVerification(onPress, {
|
||||||
|
instructions: [
|
||||||
|
<Trans key="message">
|
||||||
|
Before you can subscribe to {name}'s posts, you must first verify your
|
||||||
|
email.
|
||||||
|
</Trans>,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
accessibilityRole="button"
|
||||||
|
testID="dmBtn"
|
||||||
|
size="small"
|
||||||
|
color="secondary"
|
||||||
|
variant="solid"
|
||||||
|
shape="round"
|
||||||
|
label={_(msg`Subscribe to ${name}'s posts`)}
|
||||||
|
style={[a.justify_center]}
|
||||||
|
onPress={wrappedOnPress}>
|
||||||
|
<ButtonIcon icon={NotificationIcon} size="md" />
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<SubscribeProfileDialog
|
||||||
|
control={subscribeDialogControl}
|
||||||
|
profile={profile}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
import {useMemo, useState} from 'react'
|
||||||
|
import {View} from 'react-native'
|
||||||
|
import {msg, Trans} from '@lingui/macro'
|
||||||
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
|
import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name'
|
||||||
|
import {useTheme, web} from '#/alf'
|
||||||
|
import {atoms as a} from '#/alf'
|
||||||
|
import * as Dialog from '#/components/Dialog'
|
||||||
|
import * as Toggle from '#/components/forms/Toggle'
|
||||||
|
import {Text} from '#/components/Typography'
|
||||||
|
import type * as bsky from '#/types/bsky'
|
||||||
|
|
||||||
|
export function SubscribeProfileDialog({
|
||||||
|
control,
|
||||||
|
profile,
|
||||||
|
}: {
|
||||||
|
control: Dialog.DialogControlProps
|
||||||
|
profile: bsky.profile.AnyProfileView
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}>
|
||||||
|
<Dialog.Handle />
|
||||||
|
<DialogInner profile={profile} />
|
||||||
|
</Dialog.Outer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function DialogInner({profile}: {profile: bsky.profile.AnyProfileView}) {
|
||||||
|
const {_} = useLingui()
|
||||||
|
const t = useTheme()
|
||||||
|
const [state, setState] = useState({posts: false, replies: false})
|
||||||
|
|
||||||
|
const values = useMemo(() => {
|
||||||
|
const {posts, replies} = state
|
||||||
|
const res = []
|
||||||
|
if (posts) res.push('posts')
|
||||||
|
if (replies) res.push('replies')
|
||||||
|
return res
|
||||||
|
}, [state])
|
||||||
|
|
||||||
|
const onChange = (newValues: string[]) =>
|
||||||
|
setState({
|
||||||
|
posts: newValues.includes('posts'),
|
||||||
|
replies: newValues.includes('replies'),
|
||||||
|
})
|
||||||
|
|
||||||
|
const name = createSanitizedDisplayName(profile, false)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog.ScrollableInner
|
||||||
|
style={web({maxWidth: 400})}
|
||||||
|
label={_(msg`Subscribe to posts`)}>
|
||||||
|
<View style={[a.gap_md]}>
|
||||||
|
<View style={[a.gap_xs]}>
|
||||||
|
<Text style={[a.font_heavy, a.text_2xl]}>
|
||||||
|
<Trans>Subscribe to {name}</Trans>
|
||||||
|
</Text>
|
||||||
|
<Text style={[t.atoms.text_contrast_medium, a.text_md]}>
|
||||||
|
<Trans>Get notifications for account activity</Trans>
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Toggle.Group
|
||||||
|
label={_(msg`Subscribe to account`)}
|
||||||
|
values={values}
|
||||||
|
onChange={onChange}>
|
||||||
|
<View style={[a.gap_sm]}>
|
||||||
|
<Toggle.Item
|
||||||
|
label={_(msg`Posts`)}
|
||||||
|
name="posts"
|
||||||
|
style={[a.justify_between, a.py_xs]}>
|
||||||
|
<Toggle.LabelText
|
||||||
|
style={[t.atoms.text, a.font_normal, a.text_md]}>
|
||||||
|
<Trans>Posts</Trans>
|
||||||
|
</Toggle.LabelText>
|
||||||
|
<Toggle.Platform />
|
||||||
|
</Toggle.Item>
|
||||||
|
<Toggle.Item
|
||||||
|
label={_(msg`Replies`)}
|
||||||
|
name="replies"
|
||||||
|
style={[a.justify_between, a.py_xs]}>
|
||||||
|
<Toggle.LabelText
|
||||||
|
style={[t.atoms.text, a.font_normal, a.text_md]}>
|
||||||
|
<Trans>Replies</Trans>
|
||||||
|
</Toggle.LabelText>
|
||||||
|
<Toggle.Platform />
|
||||||
|
</Toggle.Item>
|
||||||
|
</View>
|
||||||
|
</Toggle.Group>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Dialog.Close />
|
||||||
|
</Dialog.ScrollableInner>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -30,6 +30,12 @@ export function useGlobalLabelStrings(): GlobalLabelStrings {
|
|||||||
msg`This user has requested that their content only be shown to signed-in users.`,
|
msg`This user has requested that their content only be shown to signed-in users.`,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
'!no-subscriptions': {
|
||||||
|
name: _(msg`No subscriptions allowed`),
|
||||||
|
description: _(
|
||||||
|
msg`This user has requested that they cannot be subscribed to for post notifications.`,
|
||||||
|
),
|
||||||
|
},
|
||||||
porn: {
|
porn: {
|
||||||
name: _(msg`Adult Content`),
|
name: _(msg`Adult Content`),
|
||||||
description: _(msg`Explicit sexual images.`),
|
description: _(msg`Explicit sexual images.`),
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import {
|
|||||||
KnownFollowers,
|
KnownFollowers,
|
||||||
shouldShowKnownFollowers,
|
shouldShowKnownFollowers,
|
||||||
} from '#/components/KnownFollowers'
|
} from '#/components/KnownFollowers'
|
||||||
|
import {SubscribeProfileButton} from '#/components/post-subscriptions/SubscribeProfileButton'
|
||||||
import * as Prompt from '#/components/Prompt'
|
import * as Prompt from '#/components/Prompt'
|
||||||
import {RichText} from '#/components/RichText'
|
import {RichText} from '#/components/RichText'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
@@ -134,13 +135,17 @@ let ProfileHeaderStandard = ({
|
|||||||
}
|
}
|
||||||
}, [_, queueUnblock])
|
}, [_, queueUnblock])
|
||||||
|
|
||||||
const isMe = React.useMemo(
|
const isMe = useMemo(
|
||||||
() => currentAccount?.did === profile.did,
|
() => currentAccount?.did === profile.did,
|
||||||
[currentAccount, profile],
|
[currentAccount, profile],
|
||||||
)
|
)
|
||||||
|
|
||||||
const {isActive: live} = useActorStatus(profile)
|
const {isActive: live} = useActorStatus(profile)
|
||||||
|
|
||||||
|
const subscriptionsDisallowed = useMemo(() => {
|
||||||
|
return !!profile.labels?.find(label => label.val === '!no-subscriptions')
|
||||||
|
}, [profile])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ProfileHeaderShell
|
<ProfileHeaderShell
|
||||||
profile={profile}
|
profile={profile}
|
||||||
@@ -198,6 +203,9 @@ let ProfileHeaderStandard = ({
|
|||||||
)
|
)
|
||||||
) : !profile.viewer?.blockedBy ? (
|
) : !profile.viewer?.blockedBy ? (
|
||||||
<>
|
<>
|
||||||
|
{hasSession && !subscriptionsDisallowed && (
|
||||||
|
<SubscribeProfileButton profile={profile} />
|
||||||
|
)}
|
||||||
{hasSession && <MessageProfileButton profile={profile} />}
|
{hasSession && <MessageProfileButton profile={profile} />}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
Reference in New Issue
Block a user