From 0ac15920a477a5c8090fd2b929b36ac0b6e02c34 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Fri, 18 Apr 2025 21:15:32 -0500 Subject: [PATCH] Verification (#8226) * WIP * Alignment with icon * Add create/remove prompts * Fill out check dialog a bit * Reorg * Handle was verified state * Add warning to edit profile * Add warning to handle dialog * Decent alignment in posts on all platforms * Refactor alignment for posts, chatlist, hover card * Disable on profile * Convo header * Compute simple verification state * Add other icon, rename, integrate * Swap in simple state for profile edits * Clean up utility hooks * Add verifications UI to dialog * Add edu nux * Revert change * Fix wrapping of check on profile * Rename * Fix gap under PostMeta * Update check dialogs * Handle takendown verifiers in check dialog * alf composer reply to * Refactor verification state * Add create/remove mutations, non-functional for now * Fix up post-rebase * Add check to first author noty * Do cache updates after mutations * DRY up hook, add to profile updates too * Add to drawer * Update account list * Adapt to new types * Hook up mutations * Use profile shadow in feeds * Add to settings * Shadow currentAccountProfile * Add invalid state to verifications * Fix alignment and overflow in Settings and Drawer * Re-integrate post rebase * Remove debug code * Update copy * Add unverified notification support * Remove link * Make sure dialog closes * Update URL * Add settings screen * Integrate new setting into verification states * Add metrics, bump package, fix bad import * NUX fixes * Update copy * Fixes * Update types * fix search autocomplete * fix lint * add display name warning to new dialog * update default prefs * Add parsing support for notifications * Bump pkg * Tweak noty styles * Adjust check alignment * Tweak check alignment * Fix badge for verifier * Modify copy --------- Co-authored-by: Samuel Newman Co-authored-by: Paul Frazee --- .eslintrc.js | 1 + .../circleCheck_stroke2_corner0_rounded.svg | 1 + .../icons/sparkle_stroke2_corner0_rounded.svg | 1 + assets/icons/verifiedCheck.svg | 1 + assets/icons/verifierCheck.svg | 1 + .../initial_verification_announcement_1.png | Bin 0 -> 51326 bytes .../initial_verification_announcement_2.png | Bin 0 -> 85854 bytes bskyweb/cmd/bskyweb/server.go | 1 + package.json | 2 +- src/Navigation.tsx | 9 + src/components/AccountList.tsx | 67 +++-- src/components/Link.tsx | 6 +- src/components/ProfileCard.tsx | 25 +- src/components/ProfileHoverCard/index.web.tsx | 40 ++- src/components/Prompt.tsx | 26 +- src/components/Typography.tsx | 4 +- .../nuxs/InitialVerificationAnnouncement.tsx | 194 +++++++++++++ src/components/dialogs/nuxs/index.tsx | 17 +- src/components/dms/MessagesListHeader.tsx | 49 ++-- src/components/icons/CircleCheck.tsx | 5 + src/components/icons/Sparkle.tsx | 5 + src/components/icons/VerifiedCheck.tsx | 30 ++ src/components/icons/VerifierCheck.tsx | 35 +++ .../verification/VerificationCheck.tsx | 12 + .../verification/VerificationCheckButton.tsx | 155 +++++++++++ .../verification/VerificationCreatePrompt.tsx | 70 +++++ .../verification/VerificationRemovePrompt.tsx | 50 ++++ .../verification/VerificationsDialog.tsx | 257 ++++++++++++++++++ .../verification/VerifierDialog.tsx | 153 +++++++++++ src/components/verification/index.ts | 113 ++++++++ src/lib/constants.ts | 8 + src/lib/getUserDisplayName.ts | 10 + src/lib/routes/types.ts | 1 + src/logger/metrics.ts | 13 + src/routes.ts | 1 + .../Messages/components/ChatListItem.tsx | 49 ++-- .../Moderation/VerificationSettings.tsx | 96 +++++++ src/screens/Moderation/index.tsx | 27 +- .../Profile/Header/EditProfileDialog.tsx | 27 +- .../Profile/Header/ProfileHeaderStandard.tsx | 34 ++- .../Search/components/AutocompleteResults.tsx | 2 +- .../Search/components/SearchHistory.tsx | 136 ++++++--- src/screens/Settings/Settings.tsx | 49 +++- .../components/ChangeHandleDialog.tsx | 23 +- src/state/cache/profile-shadow.ts | 4 + src/state/queries/notifications/util.ts | 26 +- src/state/queries/nuxs/definitions.ts | 6 + src/state/queries/preferences/const.ts | 7 +- src/state/queries/preferences/index.ts | 30 +- src/state/queries/profile.ts | 31 ++- .../queries/useCurrentAccountProfile.tsx | 9 + .../useUpdateProfileVerificationCache.ts | 35 +++ .../useVerificationCreateMutation.tsx | 53 ++++ .../useVerificationsRemoveMutation.tsx | 63 +++++ src/types/bsky/profile.ts | 2 +- src/view/com/composer/ComposerReplyTo.tsx | 110 ++++---- src/view/com/modals/EditProfile.tsx | 32 ++- .../notifications/NotificationFeedItem.tsx | 204 ++++++++++---- src/view/com/post-thread/PostThreadItem.tsx | 44 ++- src/view/com/profile/ProfileMenu.tsx | 52 +++- src/view/com/util/PostMeta.tsx | 175 +++++++----- src/view/shell/Drawer.tsx | 30 +- yarn.lock | 8 +- 63 files changed, 2332 insertions(+), 395 deletions(-) create mode 100644 assets/icons/circleCheck_stroke2_corner0_rounded.svg create mode 100644 assets/icons/sparkle_stroke2_corner0_rounded.svg create mode 100644 assets/icons/verifiedCheck.svg create mode 100644 assets/icons/verifierCheck.svg create mode 100644 assets/images/initial_verification_announcement_1.png create mode 100644 assets/images/initial_verification_announcement_2.png create mode 100644 src/components/dialogs/nuxs/InitialVerificationAnnouncement.tsx create mode 100644 src/components/icons/CircleCheck.tsx create mode 100644 src/components/icons/Sparkle.tsx create mode 100644 src/components/icons/VerifiedCheck.tsx create mode 100644 src/components/icons/VerifierCheck.tsx create mode 100644 src/components/verification/VerificationCheck.tsx create mode 100644 src/components/verification/VerificationCheckButton.tsx create mode 100644 src/components/verification/VerificationCreatePrompt.tsx create mode 100644 src/components/verification/VerificationRemovePrompt.tsx create mode 100644 src/components/verification/VerificationsDialog.tsx create mode 100644 src/components/verification/VerifierDialog.tsx create mode 100644 src/components/verification/index.ts create mode 100644 src/lib/getUserDisplayName.ts create mode 100644 src/screens/Moderation/VerificationSettings.tsx create mode 100644 src/state/queries/useCurrentAccountProfile.tsx create mode 100644 src/state/queries/verification/useUpdateProfileVerificationCache.ts create mode 100644 src/state/queries/verification/useVerificationCreateMutation.tsx create mode 100644 src/state/queries/verification/useVerificationsRemoveMutation.tsx diff --git a/.eslintrc.js b/.eslintrc.js index 44f3edfd17..726cc56074 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -34,6 +34,7 @@ module.exports = { 'P', 'Admonition', 'Admonition.Admonition', + 'Span', ], impliedTextProps: [], suggestedTextWrappers: { diff --git a/assets/icons/circleCheck_stroke2_corner0_rounded.svg b/assets/icons/circleCheck_stroke2_corner0_rounded.svg new file mode 100644 index 0000000000..d6b0b6bbf9 --- /dev/null +++ b/assets/icons/circleCheck_stroke2_corner0_rounded.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/sparkle_stroke2_corner0_rounded.svg b/assets/icons/sparkle_stroke2_corner0_rounded.svg new file mode 100644 index 0000000000..84478380e7 --- /dev/null +++ b/assets/icons/sparkle_stroke2_corner0_rounded.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/verifiedCheck.svg b/assets/icons/verifiedCheck.svg new file mode 100644 index 0000000000..f76955ac82 --- /dev/null +++ b/assets/icons/verifiedCheck.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/verifierCheck.svg b/assets/icons/verifierCheck.svg new file mode 100644 index 0000000000..71158eb132 --- /dev/null +++ b/assets/icons/verifierCheck.svg @@ -0,0 +1 @@ + diff --git a/assets/images/initial_verification_announcement_1.png b/assets/images/initial_verification_announcement_1.png new file mode 100644 index 0000000000000000000000000000000000000000..c7f38153b33d6e4a9de9182b27b8cf3866d8488c GIT binary patch literal 51326 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�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 z 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%0AcCWKurmu+l(RA1E}El>D}jaIeqEe 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 literal 0 HcmV?d00001 diff --git a/bskyweb/cmd/bskyweb/server.go b/bskyweb/cmd/bskyweb/server.go index b74df5ff10..f419212cc9 100644 --- a/bskyweb/cmd/bskyweb/server.go +++ b/bskyweb/cmd/bskyweb/server.go @@ -263,6 +263,7 @@ func serve(cctx *cli.Context) error { e.GET("/moderation/modlists", server.WebGeneric) e.GET("/moderation/muted-accounts", server.WebGeneric) e.GET("/moderation/blocked-accounts", server.WebGeneric) + e.GET("/moderation/verification-settings", server.WebGeneric) e.GET("/settings", server.WebGeneric) e.GET("/settings/language", server.WebGeneric) e.GET("/settings/app-passwords", server.WebGeneric) diff --git a/package.json b/package.json index 974eef74ca..235b1a91bc 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "icons:optimize": "svgo -f ./assets/icons" }, "dependencies": { - "@atproto/api": "^0.14.21", + "@atproto/api": "^0.15.3", "@bitdrift/react-native": "^0.6.8", "@braintree/sanitize-url": "^6.0.2", "@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet", diff --git a/src/Navigation.tsx b/src/Navigation.tsx index 277ffb07ec..d4fdc4797a 100644 --- a/src/Navigation.tsx +++ b/src/Navigation.tsx @@ -70,6 +70,7 @@ import {MessagesConversationScreen} from '#/screens/Messages/Conversation' import {MessagesInboxScreen} from '#/screens/Messages/Inbox' import {MessagesSettingsScreen} from '#/screens/Messages/Settings' import {ModerationScreen} from '#/screens/Moderation' +import {Screen as ModerationVerificationSettings} from '#/screens/Moderation/VerificationSettings' import {Screen as ModerationInteractionSettings} from '#/screens/ModerationInteractionSettings' import {PostLikedByScreen} from '#/screens/Post/PostLikedBy' import {PostQuotesScreen} from '#/screens/Post/PostQuotes' @@ -167,6 +168,14 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) { requireAuth: true, }} /> + ModerationVerificationSettings} + options={{ + title: title(msg`Verification Settings`), + requireAuth: true, + }} + /> SettingsScreen} diff --git a/src/components/AccountList.tsx b/src/components/AccountList.tsx index 52d149eb5a..f2e781ccf9 100644 --- a/src/components/AccountList.tsx +++ b/src/components/AccountList.tsx @@ -1,6 +1,6 @@ import React, {useCallback} from 'react' import {View} from 'react-native' -import {AppBskyActorDefs} from '@atproto/api' +import {type AppBskyActorDefs} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' @@ -12,6 +12,8 @@ import {UserAvatar} from '#/view/com/util/UserAvatar' import {atoms as a, useTheme} from '#/alf' import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check' import {ChevronRight_Stroke2_Corner0_Rounded as Chevron} from '#/components/icons/Chevron' +import {useSimpleVerificationState} from '#/components/verification' +import {VerificationCheck} from '#/components/verification/VerificationCheck' import {Button} from './Button' import {Text} from './Typography' @@ -74,11 +76,13 @@ export function AccountList({ ]}> {otherLabel ?? Other account} @@ -105,6 +109,7 @@ function AccountItem({ }) { const t = useTheme() const {_} = useLingui() + const verification = useSimpleVerificationState({profile}) const onPress = useCallback(() => { onSelect(account) @@ -114,7 +119,7 @@ function AccountItem({ + )} + + + + + + + ) +} diff --git a/src/components/dialogs/nuxs/index.tsx b/src/components/dialogs/nuxs/index.tsx index 10cae887ba..c8c539b850 100644 --- a/src/components/dialogs/nuxs/index.tsx +++ b/src/components/dialogs/nuxs/index.tsx @@ -1,16 +1,17 @@ import React from 'react' -import {AppBskyActorDefs} from '@atproto/api' +import {type AppBskyActorDefs} from '@atproto/api' import {useGate} from '#/lib/statsig/statsig' import {logger} from '#/logger' import {Nux, useNuxs, useResetNuxs, useSaveNux} from '#/state/queries/nuxs' import { usePreferencesQuery, - UsePreferencesQueryResponse, + type UsePreferencesQueryResponse, } from '#/state/queries/preferences' import {useProfileQuery} from '#/state/queries/profile' -import {SessionAccount, useSession} from '#/state/session' +import {type SessionAccount, useSession} from '#/state/session' import {useOnboardingState} from '#/state/shell' +import {InitialVerificationAnnouncement} from '#/components/dialogs/nuxs/InitialVerificationAnnouncement' /* * NUXs */ @@ -29,7 +30,12 @@ const queuedNuxs: { currentProfile: AppBskyActorDefs.ProfileViewDetailed preferences: UsePreferencesQueryResponse }) => boolean -}[] = [] +}[] = [ + { + id: Nux.InitialVerificationAnnouncement, + enabled: () => true, + }, +] const Context = React.createContext({ activeNux: undefined, @@ -163,6 +169,9 @@ function Inner({ return ( {/*For example, activeNux === Nux.NeueTypography && */} + {activeNux === Nux.InitialVerificationAnnouncement && ( + + )} ) } diff --git a/src/components/dms/MessagesListHeader.tsx b/src/components/dms/MessagesListHeader.tsx index 8da8c015f8..c8ed98f88b 100644 --- a/src/components/dms/MessagesListHeader.tsx +++ b/src/components/dms/MessagesListHeader.tsx @@ -1,9 +1,9 @@ import React, {useCallback} from 'react' import {TouchableOpacity, View} from 'react-native' import { - AppBskyActorDefs, - ModerationCause, - ModerationDecision, + type AppBskyActorDefs, + type ModerationCause, + type ModerationDecision, } from '@atproto/api' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {msg} from '@lingui/macro' @@ -12,12 +12,12 @@ import {useNavigation} from '@react-navigation/native' import {BACK_HITSLOP} from '#/lib/constants' import {makeProfileLink} from '#/lib/routes/links' -import {NavigationProp} from '#/lib/routes/types' +import {type NavigationProp} from '#/lib/routes/types' import {sanitizeDisplayName} from '#/lib/strings/display-names' import {isWeb} from '#/platform/detection' -import {Shadow} from '#/state/cache/profile-shadow' +import {type Shadow} from '#/state/cache/profile-shadow' import {isConvoActive, useConvo} from '#/state/messages/convo' -import {ConvoItem} from '#/state/messages/convo/types' +import {type ConvoItem} from '#/state/messages/convo/types' import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar' import {atoms as a, useBreakpoints, useTheme, web} from '#/alf' import {ConvoMenu} from '#/components/dms/ConvoMenu' @@ -25,6 +25,8 @@ import {Bell2Off_Filled_Corner0_Rounded as BellStroke} from '#/components/icons/ import {Link} from '#/components/Link' import {PostAlerts} from '#/components/moderation/PostAlerts' import {Text} from '#/components/Typography' +import {useSimpleVerificationState} from '#/components/verification' +import {VerificationCheck} from '#/components/verification/VerificationCheck' const PFP_SIZE = isWeb ? 40 : 34 @@ -149,6 +151,9 @@ function HeaderReady({ const {_} = useLingui() const t = useTheme() const convoState = useConvo() + const verification = useSimpleVerificationState({ + profile, + }) const isDeletedAccount = profile?.handle === 'missing.invalid' const displayName = isDeletedAccount @@ -185,17 +190,27 @@ function HeaderReady({ /> - - {displayName} - + + + {displayName} + + {verification.showBadge && ( + + + + )} + {!isDeletedAccount && ( (function LogoImpl( + props, + ref, +) { + const {fill, size, style, ...rest} = useCommonSVGProps(props) + + return ( + + + + + ) +}) diff --git a/src/components/icons/VerifierCheck.tsx b/src/components/icons/VerifierCheck.tsx new file mode 100644 index 0000000000..7c3a0149d1 --- /dev/null +++ b/src/components/icons/VerifierCheck.tsx @@ -0,0 +1,35 @@ +import React from 'react' +import Svg, {Path} from 'react-native-svg' + +import {type Props, useCommonSVGProps} from '#/components/icons/common' + +export const VerifierCheck = React.forwardRef(function LogoImpl( + props, + ref, +) { + const {fill, size, style, ...rest} = useCommonSVGProps(props) + + return ( + + + + + ) +}) diff --git a/src/components/verification/VerificationCheck.tsx b/src/components/verification/VerificationCheck.tsx new file mode 100644 index 0000000000..4f41c66824 --- /dev/null +++ b/src/components/verification/VerificationCheck.tsx @@ -0,0 +1,12 @@ +import {type Props} from '#/components/icons/common' +import {VerifiedCheck} from '#/components/icons/VerifiedCheck' +import {VerifierCheck} from '#/components/icons/VerifierCheck' + +export function VerificationCheck({ + verifier, + ...rest +}: Props & { + verifier?: boolean +}) { + return verifier ? : +} diff --git a/src/components/verification/VerificationCheckButton.tsx b/src/components/verification/VerificationCheckButton.tsx new file mode 100644 index 0000000000..1b66cd90e8 --- /dev/null +++ b/src/components/verification/VerificationCheckButton.tsx @@ -0,0 +1,155 @@ +import {View} from 'react-native' +import {msg} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {logger} from '#/logger' +import {type Shadow} from '#/state/cache/types' +import {atoms as a, useBreakpoints, useTheme} from '#/alf' +import {Button} from '#/components/Button' +import {useDialogControl} from '#/components/Dialog' +import {useFullVerificationState} from '#/components/verification' +import {type FullVerificationState} from '#/components/verification' +import {VerificationCheck} from '#/components/verification/VerificationCheck' +import {VerificationsDialog} from '#/components/verification/VerificationsDialog' +import {VerifierDialog} from '#/components/verification/VerifierDialog' +import type * as bsky from '#/types/bsky' + +export function shouldShowVerificationCheckButton( + state: FullVerificationState, +) { + let ok = false + + if (state.profile.role === 'default') { + if (state.profile.isVerified) { + ok = true + } else if (state.profile.isViewer && state.profile.wasVerified) { + ok = true + } else if ( + state.viewer.role === 'verifier' && + state.viewer.hasIssuedVerification + ) { + ok = true + } + } else if (state.profile.role === 'verifier') { + if (state.profile.isViewer) { + ok = true + } else if (state.profile.isVerified) { + ok = true + } + } + + if ( + !state.profile.showBadge && + !state.profile.isViewer && + !(state.viewer.role === 'verifier' && state.viewer.hasIssuedVerification) + ) { + ok = false + } + + return ok +} + +export function VerificationCheckButton({ + profile, + size, +}: { + profile: Shadow + size: 'lg' | 'md' | 'sm' +}) { + const state = useFullVerificationState({ + profile, + }) + + if (shouldShowVerificationCheckButton(state)) { + return + } + + return null +} + +export function Badge({ + profile, + verificationState: state, + size, +}: { + profile: Shadow + verificationState: FullVerificationState + size: 'lg' | 'md' | 'sm' +}) { + const t = useTheme() + const {_} = useLingui() + const verificationsDialogControl = useDialogControl() + const verifierDialogControl = useDialogControl() + const {gtPhone} = useBreakpoints() + let dimensions = 12 + if (size === 'lg') { + dimensions = gtPhone ? 20 : 18 + } else if (size === 'md') { + dimensions = 16 + } + + const verifiedByHidden = !state.profile.showBadge && state.profile.isViewer + + return ( + <> + + + + + + + ) +} diff --git a/src/components/verification/VerificationCreatePrompt.tsx b/src/components/verification/VerificationCreatePrompt.tsx new file mode 100644 index 0000000000..39ac6dbf61 --- /dev/null +++ b/src/components/verification/VerificationCreatePrompt.tsx @@ -0,0 +1,70 @@ +import {useCallback} from 'react' +import {View} from 'react-native' +import {msg} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {logger} from '#/logger' +import {useModerationOpts} from '#/state/preferences/moderation-opts' +import {useVerificationCreateMutation} from '#/state/queries/verification/useVerificationCreateMutation' +import * as Toast from '#/view/com/util/Toast' +import {atoms as a} from '#/alf' +import {type DialogControlProps} from '#/components/Dialog' +import {VerifiedCheck} from '#/components/icons/VerifiedCheck' +import * as ProfileCard from '#/components/ProfileCard' +import * as Prompt from '#/components/Prompt' +import type * as bsky from '#/types/bsky' + +export function VerificationCreatePrompt({ + control, + profile, +}: { + control: DialogControlProps + profile: bsky.profile.AnyProfileView +}) { + const {_} = useLingui() + const moderationOpts = useModerationOpts() + const {mutateAsync: create} = useVerificationCreateMutation() + const onConfirm = useCallback(async () => { + try { + await create({profile}) + Toast.show(_(msg`Successfully verified`)) + } catch (e) { + Toast.show(_(msg`Failed to create a verification`), 'xmark') + logger.error('Failed to create a verification', { + safeMessage: e, + }) + } + }, [_, profile, create]) + + return ( + + + + + {_(msg`Verify this account?`)} + + + + {_(msg`This action can be undone at any time.`)} + + + {moderationOpts ? ( + + + + + ) : null} + + + + + + + ) +} diff --git a/src/components/verification/VerificationRemovePrompt.tsx b/src/components/verification/VerificationRemovePrompt.tsx new file mode 100644 index 0000000000..470b61c19c --- /dev/null +++ b/src/components/verification/VerificationRemovePrompt.tsx @@ -0,0 +1,50 @@ +import {useCallback} from 'react' +import {type AppBskyActorDefs} from '@atproto/api' +import {msg} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {logger} from '#/logger' +import {useVerificationsRemoveMutation} from '#/state/queries/verification/useVerificationsRemoveMutation' +import * as Toast from '#/view/com/util/Toast' +import {type DialogControlProps} from '#/components/Dialog' +import * as Prompt from '#/components/Prompt' +import type * as bsky from '#/types/bsky' + +export {useDialogControl as usePromptControl} from '#/components/Dialog' + +export function VerificationRemovePrompt({ + control, + profile, + verifications, + onConfirm: onConfirmInner, +}: { + control: DialogControlProps + profile: bsky.profile.AnyProfileView + verifications: AppBskyActorDefs.VerificationView[] + onConfirm?: () => void +}) { + const {_} = useLingui() + const {mutateAsync: remove} = useVerificationsRemoveMutation() + const onConfirm = useCallback(async () => { + onConfirmInner?.() + try { + await remove({profile, verifications}) + Toast.show(_(msg`Removed verification`)) + } catch (e) { + Toast.show(_(msg`Failed to remove verification`), 'xmark') + logger.error('Failed to remove verification', { + safeMessage: e, + }) + } + }, [_, profile, verifications, remove, onConfirmInner]) + + return ( + + ) +} diff --git a/src/components/verification/VerificationsDialog.tsx b/src/components/verification/VerificationsDialog.tsx new file mode 100644 index 0000000000..d61823968d --- /dev/null +++ b/src/components/verification/VerificationsDialog.tsx @@ -0,0 +1,257 @@ +import {View} from 'react-native' +import {type AppBskyActorDefs} from '@atproto/api' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {urls} from '#/lib/constants' +import {getUserDisplayName} from '#/lib/getUserDisplayName' +import {logger} from '#/logger' +import {useModerationOpts} from '#/state/preferences/moderation-opts' +import {useProfileQuery} from '#/state/queries/profile' +import {useSession} from '#/state/session' +import {atoms as a, useBreakpoints, useTheme} from '#/alf' +import {Admonition} from '#/components/Admonition' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' +import * as Dialog from '#/components/Dialog' +import {useDialogControl} from '#/components/Dialog' +import {Trash_Stroke2_Corner0_Rounded as TrashIcon} from '#/components/icons/Trash' +import {Link} from '#/components/Link' +import * as ProfileCard from '#/components/ProfileCard' +import {Text} from '#/components/Typography' +import {type FullVerificationState} from '#/components/verification' +import {VerificationRemovePrompt} from '#/components/verification/VerificationRemovePrompt' +import type * as bsky from '#/types/bsky' + +export {useDialogControl} from '#/components/Dialog' + +export function VerificationsDialog({ + control, + profile, + verificationState, +}: { + control: Dialog.DialogControlProps + profile: bsky.profile.AnyProfileView + verificationState: FullVerificationState +}) { + return ( + + + + + ) +} + +function Inner({ + profile, + control, + verificationState: state, +}: { + control: Dialog.DialogControlProps + profile: bsky.profile.AnyProfileView + verificationState: FullVerificationState +}) { + const t = useTheme() + const {_} = useLingui() + const {gtMobile} = useBreakpoints() + + const userName = getUserDisplayName(profile) + const label = state.profile.isViewer + ? state.profile.isVerified + ? _(msg`You are verified`) + : _(msg`Your verifications`) + : state.profile.isVerified + ? _(msg`${userName} is verified`) + : _( + msg({ + message: `${userName}'s verifications`, + comment: `Possessive, meaning "the verifications of {userName}"`, + }), + ) + + return ( + + + + + + {label} + + + {state.profile.isVerified ? ( + + This account has a checkmark because it's been verified by trusted + sources. + + ) : ( + + This account has one or more verifications, but it is not + currently verified. + + )} + + + + {profile.verification ? ( + + + Verified by: + + + + {profile.verification.verifications.map(v => ( + + ))} + + + {profile.verification.verifications.some(v => !v.isValid) && + state.profile.isViewer && ( + + Some of your verifications are invalid. + + )} + + ) : null} + + + + { + logger.metric('verification:learn-more', { + location: 'verificationsDialog', + }) + }}> + + Learn more + + + + + + + ) +} + +function VerifierCard({ + verification, + subject, + outerDialogControl, +}: { + verification: AppBskyActorDefs.VerificationView + subject: bsky.profile.AnyProfileView + outerDialogControl: Dialog.DialogControlProps +}) { + const t = useTheme() + const {_} = useLingui() + const {currentAccount} = useSession() + const moderationOpts = useModerationOpts() + const {data: profile, error} = useProfileQuery({did: verification.issuer}) + const verificationRemovePromptControl = useDialogControl() + const canAdminister = verification.issuer === currentAccount?.did + + return ( + + + + {error ? ( + <> + + + + Unknown verifier + + + {verification.issuer} + + + + ) : profile && moderationOpts ? ( + <> + + + {canAdminister && ( + + + + )} + + ) : ( + <> + + + + )} + + + + outerDialogControl.close()} + /> + + ) +} diff --git a/src/components/verification/VerifierDialog.tsx b/src/components/verification/VerifierDialog.tsx new file mode 100644 index 0000000000..bfe49ec192 --- /dev/null +++ b/src/components/verification/VerifierDialog.tsx @@ -0,0 +1,153 @@ +import {Text as RNText, View} from 'react-native' +import {Image} from 'expo-image' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {urls} from '#/lib/constants' +import {getUserDisplayName} from '#/lib/getUserDisplayName' +import {NON_BREAKING_SPACE} from '#/lib/strings/constants' +import {logger} from '#/logger' +import {useSession} from '#/state/session' +import {atoms as a, useBreakpoints, useTheme} from '#/alf' +import {Button, ButtonText} from '#/components/Button' +import * as Dialog from '#/components/Dialog' +import {VerifierCheck} from '#/components/icons/VerifierCheck' +import {Link} from '#/components/Link' +import {Text} from '#/components/Typography' +import {type FullVerificationState} from '#/components/verification' +import type * as bsky from '#/types/bsky' + +export {useDialogControl} from '#/components/Dialog' + +export function VerifierDialog({ + control, + profile, + verificationState, +}: { + control: Dialog.DialogControlProps + profile: bsky.profile.AnyProfileView + verificationState: FullVerificationState +}) { + return ( + + + + + ) +} + +function Inner({ + profile, + control, +}: { + control: Dialog.DialogControlProps + profile: bsky.profile.AnyProfileView + verificationState: FullVerificationState +}) { + const t = useTheme() + const {_} = useLingui() + const {gtMobile} = useBreakpoints() + const {currentAccount} = useSession() + + const isSelf = profile.did === currentAccount?.did + const userName = getUserDisplayName(profile) + const label = isSelf + ? _(msg`You are a trusted verifier`) + : _(msg`${userName} is a trusted verifier`) + + return ( + + + + + + {_( + + + + + {label} + + + + Accounts with a scalloped blue check mark + + {NON_BREAKING_SPACE} + + {NON_BREAKING_SPACE} + + can verify others. These trusted verifiers are selected by + Bluesky. + + + + + + { + logger.metric('verification:learn-more', { + location: 'verifierDialog', + }) + }}> + + Learn more + + + + + + + + + ) +} diff --git a/src/components/verification/index.ts b/src/components/verification/index.ts new file mode 100644 index 0000000000..7a83a160a9 --- /dev/null +++ b/src/components/verification/index.ts @@ -0,0 +1,113 @@ +import {useMemo} from 'react' + +import {usePreferencesQuery} from '#/state/queries/preferences' +import {useCurrentAccountProfile} from '#/state/queries/useCurrentAccountProfile' +import {useSession} from '#/state/session' +import type * as bsky from '#/types/bsky' + +export type FullVerificationState = { + profile: { + role: 'default' | 'verifier' + isVerified: boolean + wasVerified: boolean + isViewer: boolean + showBadge: boolean + } + viewer: + | { + role: 'default' + isVerified: boolean + } + | { + role: 'verifier' + isVerified: boolean + hasIssuedVerification: boolean + } +} + +export function useFullVerificationState({ + profile, +}: { + profile: bsky.profile.AnyProfileView +}): FullVerificationState { + const {currentAccount} = useSession() + const currentAccountProfile = useCurrentAccountProfile() + const profileState = useSimpleVerificationState({profile}) + const viewerState = useSimpleVerificationState({ + profile: currentAccountProfile, + }) + + return useMemo(() => { + const verifications = profile.verification?.verifications || [] + const wasVerified = + profileState.role === 'default' && + !profileState.isVerified && + verifications.length > 0 + const hasIssuedVerification = Boolean( + viewerState && + viewerState.role === 'verifier' && + profileState.role === 'default' && + verifications.find(v => v.issuer === currentAccount?.did), + ) + + return { + profile: { + ...profileState, + wasVerified, + isViewer: profile.did === currentAccount?.did, + showBadge: profileState.showBadge, + }, + viewer: + viewerState.role === 'verifier' + ? { + role: 'verifier', + isVerified: viewerState.isVerified, + hasIssuedVerification, + } + : { + role: 'default', + isVerified: viewerState.isVerified, + }, + } + }, [profile, currentAccount, profileState, viewerState]) +} + +export type SimpleVerificationState = { + role: 'default' | 'verifier' + isVerified: boolean + showBadge: boolean +} + +export function useSimpleVerificationState({ + profile, +}: { + profile?: bsky.profile.AnyProfileView +}): SimpleVerificationState { + const preferences = usePreferencesQuery() + const prefs = useMemo( + () => preferences.data?.verificationPrefs || {hideBadges: false}, + [preferences.data?.verificationPrefs], + ) + return useMemo(() => { + if (!profile || !profile.verification) { + return { + role: 'default', + isVerified: false, + showBadge: false, + } + } + + const {verifiedStatus, trustedVerifierStatus} = profile.verification + const isVerifiedUser = ['valid', 'invalid'].includes(verifiedStatus) + const isVerifierUser = ['valid', 'invalid'].includes(trustedVerifierStatus) + const isVerified = + (isVerifiedUser && verifiedStatus === 'valid') || + (isVerifierUser && trustedVerifierStatus === 'valid') + + return { + role: isVerifierUser ? 'verifier' : 'default', + isVerified, + showBadge: prefs.hideBadges ? false : isVerified, + } + }, [profile, prefs]) +} diff --git a/src/lib/constants.ts b/src/lib/constants.ts index fe84f41b2f..bb98f9fc8e 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -192,3 +192,11 @@ export const SUPPORTED_MIME_TYPES = [ export type SupportedMimeTypes = (typeof SUPPORTED_MIME_TYPES)[number] export const EMOJI_REACTION_LIMIT = 5 + +export const urls = { + website: { + blog: { + initialVerificationAnnouncement: `https://bsky.social/about/blog/04-21-2025-verification`, + }, + }, +} diff --git a/src/lib/getUserDisplayName.ts b/src/lib/getUserDisplayName.ts new file mode 100644 index 0000000000..790bb31e5d --- /dev/null +++ b/src/lib/getUserDisplayName.ts @@ -0,0 +1,10 @@ +import {sanitizeDisplayName} from '#/lib/strings/display-names' +import {sanitizeHandle} from '#/lib/strings/handles' + +export function getUserDisplayName< + T extends {displayName?: string; handle: string; [key: string]: any}, +>(props: T): string { + return sanitizeDisplayName( + props.displayName || sanitizeHandle(props.handle, '@'), + ) +} diff --git a/src/lib/routes/types.ts b/src/lib/routes/types.ts index 658b68db85..0bc85b630c 100644 --- a/src/lib/routes/types.ts +++ b/src/lib/routes/types.ts @@ -13,6 +13,7 @@ export type CommonNavigatorParams = { ModerationMutedAccounts: undefined ModerationBlockedAccounts: undefined ModerationInteractionSettings: undefined + ModerationVerificationSettings: undefined Settings: undefined Profile: {name: string; hideBackButton?: boolean} ProfileFollowers: {name: string} diff --git a/src/logger/metrics.ts b/src/logger/metrics.ts index 2b696c1e42..42b0d6ef35 100644 --- a/src/logger/metrics.ts +++ b/src/logger/metrics.ts @@ -370,4 +370,17 @@ export type MetricEvents = { targetLanguage: string textLength: number } + + 'verification:create': {} + 'verification:revoke': {} + 'verification:badge:click': {} + 'verification:learn-more': { + location: + | 'initialAnnouncementeNux' + | 'verificationsDialog' + | 'verifierDialog' + | 'verificationSettings' + } + 'verification:settings:hideBadges': {} + 'verification:settings:unHideBadges': {} } diff --git a/src/routes.ts b/src/routes.ts index 68c39e7fca..60bb65dd5a 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -14,6 +14,7 @@ export const router = new Router({ ModerationMutedAccounts: '/moderation/muted-accounts', ModerationBlockedAccounts: '/moderation/blocked-accounts', ModerationInteractionSettings: '/moderation/interaction-settings', + ModerationVerificationSettings: '/moderation/verification-settings', // profiles, threads, lists Profile: ['/profile/:name', '/profile/:name/rss'], ProfileFollowers: '/profile/:name/followers', diff --git a/src/screens/Messages/components/ChatListItem.tsx b/src/screens/Messages/components/ChatListItem.tsx index 8a760e2c9b..09cf2dccd6 100644 --- a/src/screens/Messages/components/ChatListItem.tsx +++ b/src/screens/Messages/components/ChatListItem.tsx @@ -43,6 +43,8 @@ import {Link} from '#/components/Link' import {useMenuControl} from '#/components/Menu' import {PostAlerts} from '#/components/moderation/PostAlerts' import {Text} from '#/components/Typography' +import {useSimpleVerificationState} from '#/components/verification' +import {VerificationCheck} from '#/components/verification/VerificationCheck' import type * as bsky from '#/types/bsky' export let ChatListItem = ({ @@ -106,6 +108,9 @@ function ChatListItemReady({ const playHaptic = useHaptics() const queryClient = useQueryClient() const isUnread = convo.unreadCount > 0 + const verification = useSimpleVerificationState({ + profile, + }) const blockInfo = useMemo(() => { const modui = moderation.ui('profileView') @@ -385,11 +390,10 @@ function ChatListItemReady({ - + {displayName} - + + {verification.showBadge && ( + + + + )} {lastMessageSentAt && ( - - {({timeElapsed}) => ( - - {' '} - · {timeElapsed} - - )} - + + + {({timeElapsed}) => ( + + · {timeElapsed} + + )} + + )} {(convo.muted || moderation.blocked) && ( + + + + + Verification Settings + + + + + + + + + + Verifications on Bluesky work differently than on other + platforms.{' '} + { + logger.metric('verification:learn-more', { + location: 'verificationSettings', + }) + }}> + Learn more here. + + + + + {preferences ? ( + + ) : ( + + + + )} + + + + ) +} + +function Inner({preferences}: {preferences: UsePreferencesQueryResponse}) { + const {_} = useLingui() + const {hideBadges} = preferences.verificationPrefs + const {mutate: setVerificationPrefs, isPending} = + useSetVerificationPrefsMutation() + + return ( + { + setVerificationPrefs({hideBadges: value}) + }}> + + + + Hide verification badges + + + + + ) +} diff --git a/src/screens/Moderation/index.tsx b/src/screens/Moderation/index.tsx index 55cc67f8c3..78b0a6ae9d 100644 --- a/src/screens/Moderation/index.tsx +++ b/src/screens/Moderation/index.tsx @@ -6,19 +6,22 @@ import {useLingui} from '@lingui/react' import {useFocusEffect} from '@react-navigation/native' import {getLabelingServiceTitle} from '#/lib/moderation' -import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' +import { + type CommonNavigatorParams, + type NativeStackScreenProps, +} from '#/lib/routes/types' import {logger} from '#/logger' import {isIOS} from '#/platform/detection' import { useMyLabelersQuery, usePreferencesQuery, - UsePreferencesQueryResponse, + type UsePreferencesQueryResponse, usePreferencesSetAdultContentMutation, } from '#/state/queries/preferences' import {isNonConfigurableModerationAuthority} from '#/state/session/additional-moderation-authorities' import {useSetMinimalShellMode} from '#/state/shell' import {ViewHeader} from '#/view/com/util/ViewHeader' -import {atoms as a, useBreakpoints, useTheme, ViewStyleProp} from '#/alf' +import {atoms as a, useBreakpoints, useTheme, type ViewStyleProp} from '#/alf' import {Button, ButtonText} from '#/components/Button' import * as Dialog from '#/components/Dialog' import {BirthDateSettingsDialog} from '#/components/dialogs/BirthDateSettings' @@ -27,7 +30,8 @@ import {Divider} from '#/components/Divider' import * as Toggle from '#/components/forms/Toggle' import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron' import {CircleBanSign_Stroke2_Corner0_Rounded as CircleBanSign} from '#/components/icons/CircleBanSign' -import {Props as SVGIconProps} from '#/components/icons/common' +import {CircleCheck_Stroke2_Corner0_Rounded as CircleCheck} from '#/components/icons/CircleCheck' +import {type Props as SVGIconProps} from '#/components/icons/common' import {EditBig_Stroke2_Corner0_Rounded as EditBig} from '#/components/icons/EditBig' import {Filter_Stroke2_Corner0_Rounded as Filter} from '#/components/icons/Filter' import {Group3_Stroke2_Corner0_Rounded as Group} from '#/components/icons/Group' @@ -274,6 +278,21 @@ export function ModerationScreenInner({ /> )} + + + {state => ( + + )} + + {verification.isVerified && + verification.role === 'default' && + displayName !== initialDisplayName && ( + + + You are verified. You will lose your verification status if you + change your display name.{' '} + + Learn more. + + + + )} + Description diff --git a/src/screens/Profile/Header/ProfileHeaderStandard.tsx b/src/screens/Profile/Header/ProfileHeaderStandard.tsx index 773c296c94..1c4c4d9f32 100644 --- a/src/screens/Profile/Header/ProfileHeaderStandard.tsx +++ b/src/screens/Profile/Header/ProfileHeaderStandard.tsx @@ -10,6 +10,7 @@ import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {sanitizeDisplayName} from '#/lib/strings/display-names' +import {sanitizeHandle} from '#/lib/strings/handles' import {logger} from '#/logger' import {isIOS, isWeb} from '#/platform/detection' import {useProfileShadow} from '#/state/cache/profile-shadow' @@ -22,7 +23,7 @@ import { import {useRequireAuth, useSession} from '#/state/session' import {ProfileMenu} from '#/view/com/profile/ProfileMenu' import * as Toast from '#/view/com/util/Toast' -import {atoms as a} from '#/alf' +import {atoms as a, platform, useBreakpoints, useTheme} from '#/alf' import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {useDialogControl} from '#/components/Dialog' import {MessageProfileButton} from '#/components/dms/MessageProfileButton' @@ -33,7 +34,8 @@ import { } from '#/components/KnownFollowers' import * as Prompt from '#/components/Prompt' import {RichText} from '#/components/RichText' -import {ProfileHeaderDisplayName} from './DisplayName' +import {Text} from '#/components/Typography' +import {VerificationCheckButton} from '#/components/verification/VerificationCheckButton' import {EditProfileDialog} from './EditProfileDialog' import {ProfileHeaderHandle} from './Handle' import {ProfileHeaderMetrics} from './Metrics' @@ -54,6 +56,8 @@ let ProfileHeaderStandard = ({ hideBackButton = false, isPlaceholderProfile, }: Props): React.ReactNode => { + const t = useTheme() + const {gtMobile} = useBreakpoints() const profile: Shadow = useProfileShadow(profileUnshadowed) const {currentAccount, hasSession} = useSession() @@ -238,7 +242,31 @@ let ProfileHeaderStandard = ({ - + + + {sanitizeDisplayName( + profile.displayName || sanitizeHandle(profile.handle), + moderation.ui('displayName'), + )} + + + + + {!isPlaceholderProfile && !isBlockedUser && ( diff --git a/src/screens/Search/components/AutocompleteResults.tsx b/src/screens/Search/components/AutocompleteResults.tsx index b3bccd1d4b..2824ccc1ba 100644 --- a/src/screens/Search/components/AutocompleteResults.tsx +++ b/src/screens/Search/components/AutocompleteResults.tsx @@ -49,7 +49,7 @@ let AutocompleteResults = ({ ? undefined : `/search?q=${encodeURIComponent(searchText)}` } - style={{borderBottomWidth: 1}} + style={a.border_b} /> {autocompleteData?.map(item => ( void }) { const {gtMobile} = useBreakpoints() - const t = useTheme() const {_} = useLingui() + const moderationOpts = useModerationOpts() return ( - {selectedProfiles.slice(0, 5).map((profile, index) => ( - - onProfileClick(profile)} - style={[a.align_center, a.w_full]}> - ( + onProfileClick(profile)} + onRemove={() => onRemoveProfileClick(profile)} /> - - {sanitizeDisplayName( - profile.displayName || profile.handle, - )} - - - onRemoveProfileClick(profile)} - hitSlop={createHitslop(6)} - style={styles.profileRemoveBtn}> - - - - ))} + ))} @@ -134,6 +111,81 @@ export function SearchHistory({ ) } +function RecentProfileItem({ + profile, + moderationOpts, + onPress, + onRemove, +}: { + profile: bsky.profile.AnyProfileView + moderationOpts: ModerationOpts + onPress: () => void + onRemove: () => void +}) { + const {_} = useLingui() + const {gtMobile} = useBreakpoints() + const t = useTheme() + + const moderation = moderateProfile(profile, moderationOpts) + const name = sanitizeDisplayName( + profile.displayName || sanitizeHandle(profile.handle), + moderation.ui('displayName'), + ) + const verification = useSimpleVerificationState({profile}) + + return ( + + + + + + + {name} + + {verification.showBadge && ( + + + + )} + + + + + + + + ) +} + const styles = StyleSheet.create({ selectedProfilesContainer: { marginTop: 10, diff --git a/src/screens/Settings/Settings.tsx b/src/screens/Settings/Settings.tsx index 956413a553..a723aaa379 100644 --- a/src/screens/Settings/Settings.tsx +++ b/src/screens/Settings/Settings.tsx @@ -29,7 +29,7 @@ import {useCloseAllActiveElements} from '#/state/util' import * as Toast from '#/view/com/util/Toast' import {UserAvatar} from '#/view/com/util/UserAvatar' import * as SettingsList from '#/screens/Settings/components/SettingsList' -import {atoms as a, tokens, useBreakpoints, useTheme} from '#/alf' +import {atoms as a, platform, tokens, useBreakpoints, useTheme} from '#/alf' import {AvatarStackWithFetch} from '#/components/AvatarStack' import {useDialogControl} from '#/components/Dialog' import {SwitchAccountDialog} from '#/components/dialogs/SwitchAccount' @@ -55,6 +55,11 @@ import {Loader} from '#/components/Loader' import * as Menu from '#/components/Menu' import * as Prompt from '#/components/Prompt' import {Text} from '#/components/Typography' +import {useFullVerificationState} from '#/components/verification' +import { + shouldShowVerificationCheckButton, + VerificationCheckButton, +} from '#/components/verification/VerificationCheckButton' type Props = NativeStackScreenProps export function SettingsScreen({}: Props) { @@ -278,6 +283,9 @@ function ProfilePreview({ const {gtMobile} = useBreakpoints() const shadow = useProfileShadow(profile) const moderationOpts = useModerationOpts() + const verificationState = useFullVerificationState({ + profile: shadow, + }) if (!moderationOpts) return null @@ -292,20 +300,33 @@ function ProfilePreview({ type={shadow.associated?.labeler ? 'labeler' : 'user'} /> - - {sanitizeDisplayName( - profile.displayName || sanitizeHandle(profile.handle), - moderation.ui('displayName'), + + + {sanitizeDisplayName( + profile.displayName || sanitizeHandle(profile.handle), + moderation.ui('displayName'), + )} + + {shouldShowVerificationCheckButton(verificationState) && ( + + + )} - + {sanitizeHandle(profile.handle, '@')} diff --git a/src/screens/Settings/components/ChangeHandleDialog.tsx b/src/screens/Settings/components/ChangeHandleDialog.tsx index b69713a10e..a39d958ab8 100644 --- a/src/screens/Settings/components/ChangeHandleDialog.tsx +++ b/src/screens/Settings/components/ChangeHandleDialog.tsx @@ -10,18 +10,19 @@ import Animated, { SlideOutLeft, SlideOutRight, } from 'react-native-reanimated' -import {ComAtprotoServerDescribeServer} from '@atproto/api' +import {type ComAtprotoServerDescribeServer} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useMutation, useQueryClient} from '@tanstack/react-query' -import {HITSLOP_10} from '#/lib/constants' +import {HITSLOP_10, urls} from '#/lib/constants' import {cleanError} from '#/lib/strings/errors' import {createFullHandle, validateServiceHandle} from '#/lib/strings/handles' import {sanitizeHandle} from '#/lib/strings/handles' import {useFetchDid, useUpdateHandleMutation} from '#/state/queries/handle' import {RQKEY as RQKEY_PROFILE} from '#/state/queries/profile' import {useServiceQuery} from '#/state/queries/service' +import {useCurrentAccountProfile} from '#/state/queries/useCurrentAccountProfile' import {useAgent, useSession} from '#/state/session' import {ErrorScreen} from '#/view/com/util/error/ErrorScreen' import {atoms as a, native, useBreakpoints, useTheme} from '#/alf' @@ -40,6 +41,7 @@ import {SquareBehindSquare4_Stroke2_Corner0_Rounded as CopyIcon} from '#/compone import {InlineLinkText} from '#/components/Link' import {Loader} from '#/components/Loader' import {Text} from '#/components/Typography' +import {useSimpleVerificationState} from '#/components/verification' import {CopyButton} from './CopyButton' export function ChangeHandleDialog({ @@ -152,6 +154,10 @@ function ProvidedHandlePage({ const control = Dialog.useDialogContext() const {currentAccount} = useSession() const queryClient = useQueryClient() + const profile = useCurrentAccountProfile() + const verification = useSimpleVerificationState({ + profile, + }) const { mutate: changeHandle, @@ -197,6 +203,19 @@ function ProvidedHandlePage({ + {verification.isVerified && verification.role === 'default' && ( + + + You are verified. You will lose your verification status if you + change your handle.{' '} + + Learn more. + + + + )} New handle diff --git a/src/state/cache/profile-shadow.ts b/src/state/cache/profile-shadow.ts index 82ee44388f..9c23e4550a 100644 --- a/src/state/cache/profile-shadow.ts +++ b/src/state/cache/profile-shadow.ts @@ -1,4 +1,5 @@ import {useEffect, useMemo, useState} from 'react' +import {type AppBskyActorDefs} from '@atproto/api' import {type QueryClient} from '@tanstack/react-query' import EventEmitter from 'eventemitter3' @@ -29,6 +30,7 @@ export interface ProfileShadow { followingUri: string | undefined muted: boolean | undefined blockingUri: string | undefined + verification: AppBskyActorDefs.VerificationState } const shadows: WeakMap< @@ -134,6 +136,8 @@ function mergeShadow( blocking: 'blockingUri' in shadow ? shadow.blockingUri : profile.viewer?.blocking, }, + verification: + 'verification' in shadow ? shadow.verification : profile.verification, }) } diff --git a/src/state/queries/notifications/util.ts b/src/state/queries/notifications/util.ts index f6f53f58fe..6bbf9b250e 100644 --- a/src/state/queries/notifications/util.ts +++ b/src/state/queries/notifications/util.ts @@ -1,22 +1,26 @@ import { - AppBskyFeedDefs, + type AppBskyFeedDefs, AppBskyFeedLike, AppBskyFeedPost, AppBskyFeedRepost, - AppBskyGraphDefs, + type AppBskyGraphDefs, AppBskyGraphStarterpack, - AppBskyNotificationListNotifications, - BskyAgent, + type AppBskyNotificationListNotifications, + type BskyAgent, moderateNotification, - ModerationOpts, + type ModerationOpts, } from '@atproto/api' -import {QueryClient} from '@tanstack/react-query' +import {type QueryClient} from '@tanstack/react-query' import chunk from 'lodash.chunk' import {labelIsHideableOffense} from '#/lib/moderation' import * as bsky from '#/types/bsky' import {precacheProfile} from '../profile' -import {FeedNotification, FeedPage, NotificationType} from './types' +import { + type FeedNotification, + type FeedPage, + type NotificationType, +} from './types' const GROUPABLE_REASONS = ['like', 'repost', 'follow'] const MS_1HR = 1e3 * 60 * 60 @@ -155,14 +159,14 @@ export function groupNotifications( const type = toKnownType(notif) if (type !== 'starterpack-joined') { groupedNotifs.push({ - _reactKey: `notif-${notif.uri}`, + _reactKey: `notif-${notif.uri}-${notif.reason}`, type, notification: notif, subjectUri: getSubjectUri(type, notif), }) } else { groupedNotifs.push({ - _reactKey: `notif-${notif.uri}`, + _reactKey: `notif-${notif.uri}-${notif.reason}`, type: 'starterpack-joined', notification: notif, subjectUri: notif.uri, @@ -238,7 +242,9 @@ function toKnownType( notif.reason === 'reply' || notif.reason === 'quote' || notif.reason === 'follow' || - notif.reason === 'starterpack-joined' + notif.reason === 'starterpack-joined' || + notif.reason === 'verified' || + notif.reason === 'unverified' ) { return notif.reason as NotificationType } diff --git a/src/state/queries/nuxs/definitions.ts b/src/state/queries/nuxs/definitions.ts index 8eb53a0a43..a44ffa4c54 100644 --- a/src/state/queries/nuxs/definitions.ts +++ b/src/state/queries/nuxs/definitions.ts @@ -5,6 +5,7 @@ import {type BaseNux} from '#/state/queries/nuxs/types' export enum Nux { NeueTypography = 'NeueTypography', ExploreInterestsCard = 'ExploreInterestsCard', + InitialVerificationAnnouncement = 'InitialVerificationAnnouncement', } export const nuxNames = new Set(Object.values(Nux)) @@ -18,9 +19,14 @@ export type AppNux = BaseNux< id: Nux.ExploreInterestsCard data: undefined } + | { + id: Nux.InitialVerificationAnnouncement + data: undefined + } > export const NuxSchemas: Record | undefined> = { [Nux.NeueTypography]: undefined, [Nux.ExploreInterestsCard]: undefined, + [Nux.InitialVerificationAnnouncement]: undefined, } diff --git a/src/state/queries/preferences/const.ts b/src/state/queries/preferences/const.ts index 3c1fead5e8..84b208a9f7 100644 --- a/src/state/queries/preferences/const.ts +++ b/src/state/queries/preferences/const.ts @@ -1,7 +1,7 @@ import {DEFAULT_LOGGED_OUT_LABEL_PREFERENCES} from '#/state/queries/preferences/moderation' import { - ThreadViewPreferences, - UsePreferencesQueryResponse, + type ThreadViewPreferences, + type UsePreferencesQueryResponse, } from '#/state/queries/preferences/types' export const DEFAULT_HOME_FEED_PREFS: UsePreferencesQueryResponse['feedViewPrefs'] = @@ -43,4 +43,7 @@ export const DEFAULT_LOGGED_OUT_PREFERENCES: UsePreferencesQueryResponse = { threadgateAllowRules: undefined, postgateEmbeddingRules: [], }, + verificationPrefs: { + hideBadges: false, + }, } diff --git a/src/state/queries/preferences/index.ts b/src/state/queries/preferences/index.ts index 81b3dd086b..daab5eca35 100644 --- a/src/state/queries/preferences/index.ts +++ b/src/state/queries/preferences/index.ts @@ -1,7 +1,7 @@ import { - AppBskyActorDefs, - BskyFeedViewPreference, - LabelPreference, + type AppBskyActorDefs, + type BskyFeedViewPreference, + type LabelPreference, } from '@atproto/api' import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query' @@ -16,8 +16,8 @@ import { DEFAULT_THREAD_VIEW_PREFS, } from '#/state/queries/preferences/const' import { - ThreadViewPreferences, - UsePreferencesQueryResponse, + type ThreadViewPreferences, + type UsePreferencesQueryResponse, } from '#/state/queries/preferences/types' import {useAgent} from '#/state/session' import {saveLabelers} from '#/state/session/agent-config' @@ -407,3 +407,23 @@ export function useSetActiveProgressGuideMutation() { }, }) } + +export function useSetVerificationPrefsMutation() { + const queryClient = useQueryClient() + const agent = useAgent() + + return useMutation({ + mutationFn: async prefs => { + await agent.setVerificationPrefs(prefs) + if (prefs.hideBadges) { + logger.metric('verification:settings:hideBadges', {}) + } else { + logger.metric('verification:settings:unHideBadges', {}) + } + // triggers a refetch + await queryClient.invalidateQueries({ + queryKey: preferencesQueryKey, + }) + }, + }) +} diff --git a/src/state/queries/profile.ts b/src/state/queries/profile.ts index 2cf144d3a2..609a62e25a 100644 --- a/src/state/queries/profile.ts +++ b/src/state/queries/profile.ts @@ -1,18 +1,18 @@ import {useCallback} from 'react' -import {Image as RNImage} from 'react-native-image-crop-picker' +import {type Image as RNImage} from 'react-native-image-crop-picker' import { - AppBskyActorDefs, - AppBskyActorGetProfile, - AppBskyActorGetProfiles, - AppBskyActorProfile, + type AppBskyActorDefs, + type AppBskyActorGetProfile, + type AppBskyActorGetProfiles, + type AppBskyActorProfile, AtUri, - BskyAgent, - ComAtprotoRepoUploadBlob, - Un$Typed, + type BskyAgent, + type ComAtprotoRepoUploadBlob, + type Un$Typed, } from '@atproto/api' import { keepPreviousData, - QueryClient, + type QueryClient, useMutation, useQuery, useQueryClient, @@ -21,16 +21,17 @@ import { import {uploadBlob} from '#/lib/api' import {until} from '#/lib/async/until' import {useToggleMutationQueue} from '#/lib/hooks/useToggleMutationQueue' -import {logEvent, LogEvents, toClout} from '#/lib/statsig/statsig' -import {Shadow} from '#/state/cache/types' +import {logEvent, type LogEvents, toClout} from '#/lib/statsig/statsig' +import {type Shadow} from '#/state/cache/types' import {STALE} from '#/state/queries' import {resetProfilePostsQueries} from '#/state/queries/post-feed' import { unstableCacheProfileView, useUnstableProfileViewCache, } from '#/state/queries/unstable-profile-cache' +import {useUpdateProfileVerificationCache} from '#/state/queries/verification/useUpdateProfileVerificationCache' import * as userActionHistory from '#/state/userActionHistory' -import * as bsky from '#/types/bsky' +import type * as bsky from '#/types/bsky' import {updateProfileShadow} from '../cache/profile-shadow' import {useAgent, useSession} from '../session' import { @@ -50,7 +51,7 @@ export const precacheProfile = unstableCacheProfileView const RQKEY_ROOT = 'profile' export const RQKEY = (did: string) => [RQKEY_ROOT, did] -const profilesQueryKeyRoot = 'profiles' +export const profilesQueryKeyRoot = 'profiles' export const profilesQueryKey = (handles: string[]) => [ profilesQueryKeyRoot, handles, @@ -137,6 +138,7 @@ interface ProfileUpdateParams { export function useProfileUpdateMutation() { const queryClient = useQueryClient() const agent = useAgent() + const updateProfileVerificationCache = useUpdateProfileVerificationCache() return useMutation({ mutationFn: async ({ profile, @@ -223,7 +225,7 @@ export function useProfileUpdateMutation() { }), ) }, - onSuccess(data, variables) { + async onSuccess(_, variables) { // invalidate cache queryClient.invalidateQueries({ queryKey: RQKEY(variables.profile.did), @@ -231,6 +233,7 @@ export function useProfileUpdateMutation() { queryClient.invalidateQueries({ queryKey: [profilesQueryKeyRoot, [variables.profile.did]], }) + await updateProfileVerificationCache({profile: variables.profile}) }, }) } diff --git a/src/state/queries/useCurrentAccountProfile.tsx b/src/state/queries/useCurrentAccountProfile.tsx new file mode 100644 index 0000000000..d1f562efc4 --- /dev/null +++ b/src/state/queries/useCurrentAccountProfile.tsx @@ -0,0 +1,9 @@ +import {useMaybeProfileShadow} from '#/state/cache/profile-shadow' +import {useProfileQuery} from '#/state/queries/profile' +import {useSession} from '#/state/session' + +export function useCurrentAccountProfile() { + const {currentAccount} = useSession() + const {data: profile} = useProfileQuery({did: currentAccount?.did}) + return useMaybeProfileShadow(profile) +} diff --git a/src/state/queries/verification/useUpdateProfileVerificationCache.ts b/src/state/queries/verification/useUpdateProfileVerificationCache.ts new file mode 100644 index 0000000000..f5ccf1458b --- /dev/null +++ b/src/state/queries/verification/useUpdateProfileVerificationCache.ts @@ -0,0 +1,35 @@ +import {useCallback} from 'react' +import {useQueryClient} from '@tanstack/react-query' + +import {logger} from '#/logger' +import {updateProfileShadow} from '#/state/cache/profile-shadow' +import {useAgent} from '#/state/session' +import type * as bsky from '#/types/bsky' + +/** + * Fetches a fresh verification state from the app view and updates our profile + * cache. This state is computed using a variety of factors on the server, so + * we need to get this data from the server. + */ +export function useUpdateProfileVerificationCache() { + const qc = useQueryClient() + const agent = useAgent() + + return useCallback( + async ({profile}: {profile: bsky.profile.AnyProfileView}) => { + try { + const {data: updated} = await agent.getProfile({ + actor: profile.did ?? '', + }) + updateProfileShadow(qc, profile.did, { + verification: updated.verification, + }) + } catch (e) { + logger.error(`useUpdateProfileVerificationCache failed`, { + safeMessage: e, + }) + } + }, + [agent, qc], + ) +} diff --git a/src/state/queries/verification/useVerificationCreateMutation.tsx b/src/state/queries/verification/useVerificationCreateMutation.tsx new file mode 100644 index 0000000000..1048eb9d2c --- /dev/null +++ b/src/state/queries/verification/useVerificationCreateMutation.tsx @@ -0,0 +1,53 @@ +import {type AppBskyActorGetProfile} from '@atproto/api' +import {useMutation} from '@tanstack/react-query' + +import {until} from '#/lib/async/until' +import {logger} from '#/logger' +import {useUpdateProfileVerificationCache} from '#/state/queries/verification/useUpdateProfileVerificationCache' +import {useAgent, useSession} from '#/state/session' +import type * as bsky from '#/types/bsky' + +export function useVerificationCreateMutation() { + const agent = useAgent() + const {currentAccount} = useSession() + const updateProfileVerificationCache = useUpdateProfileVerificationCache() + + return useMutation({ + async mutationFn({profile}: {profile: bsky.profile.AnyProfileView}) { + if (!currentAccount) { + throw new Error('User not logged in') + } + + const {uri} = await agent.app.bsky.graph.verification.create( + {repo: currentAccount.did}, + { + subject: profile.did, + createdAt: new Date().toISOString(), + handle: profile.handle, + displayName: profile.displayName || '', + }, + ) + + await until( + 5, + 1e3, + ({data: profile}: AppBskyActorGetProfile.Response) => { + if ( + profile.verification && + profile.verification.verifications.find(v => v.uri === uri) + ) { + return true + } + return false + }, + () => { + return agent.getProfile({actor: profile.did ?? ''}) + }, + ) + }, + async onSuccess(_, {profile}) { + logger.metric('verification:create', {}) + await updateProfileVerificationCache({profile}) + }, + }) +} diff --git a/src/state/queries/verification/useVerificationsRemoveMutation.tsx b/src/state/queries/verification/useVerificationsRemoveMutation.tsx new file mode 100644 index 0000000000..936c786c9a --- /dev/null +++ b/src/state/queries/verification/useVerificationsRemoveMutation.tsx @@ -0,0 +1,63 @@ +import { + type AppBskyActorDefs, + type AppBskyActorGetProfile, + AtUri, +} from '@atproto/api' +import {useMutation} from '@tanstack/react-query' + +import {until} from '#/lib/async/until' +import {logger} from '#/logger' +import {useUpdateProfileVerificationCache} from '#/state/queries/verification/useUpdateProfileVerificationCache' +import {useAgent, useSession} from '#/state/session' +import type * as bsky from '#/types/bsky' + +export function useVerificationsRemoveMutation() { + const agent = useAgent() + const {currentAccount} = useSession() + const updateProfileVerificationCache = useUpdateProfileVerificationCache() + + return useMutation({ + async mutationFn({ + profile, + verifications, + }: { + profile: bsky.profile.AnyProfileView + verifications: AppBskyActorDefs.VerificationView[] + }) { + if (!currentAccount) { + throw new Error('User not logged in') + } + + const uris = verifications.map(v => v.uri) + + await Promise.all( + uris.map(uri => { + return agent.app.bsky.graph.verification.delete({ + repo: currentAccount.did, + rkey: new AtUri(uri).rkey, + }) + }), + ) + + await until( + 5, + 1e3, + ({data: profile}: AppBskyActorGetProfile.Response) => { + if ( + !profile.verification?.verifications.some(v => uris.includes(v.uri)) + ) { + return true + } + return false + }, + () => { + return agent.getProfile({actor: profile.did ?? ''}) + }, + ) + }, + async onSuccess(_, {profile}) { + logger.metric('verification:revoke', {}) + await updateProfileVerificationCache({profile}) + }, + }) +} diff --git a/src/types/bsky/profile.ts b/src/types/bsky/profile.ts index 7449f117e3..12c8146ae1 100644 --- a/src/types/bsky/profile.ts +++ b/src/types/bsky/profile.ts @@ -1,4 +1,4 @@ -import {AppBskyActorDefs, ChatBskyActorDefs} from '@atproto/api' +import {type AppBskyActorDefs, type ChatBskyActorDefs} from '@atproto/api' /** * Matches any profile view exported by our SDK diff --git a/src/view/com/composer/ComposerReplyTo.tsx b/src/view/com/composer/ComposerReplyTo.tsx index 2766fe6257..5da530768d 100644 --- a/src/view/com/composer/ComposerReplyTo.tsx +++ b/src/view/com/composer/ComposerReplyTo.tsx @@ -1,5 +1,5 @@ -import React from 'react' -import {LayoutAnimation, Pressable, StyleSheet, View} from 'react-native' +import {useCallback, useMemo, useState} from 'react' +import {LayoutAnimation, Pressable, View} from 'react-native' import {Image} from 'expo-image' import { AppBskyEmbedImages, @@ -12,20 +12,22 @@ import {useLingui} from '@lingui/react' import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeHandle} from '#/lib/strings/handles' -import {ComposerOptsPostRef} from '#/state/shell/composer' +import {type ComposerOptsPostRef} from '#/state/shell/composer' import {MaybeQuoteEmbed} from '#/view/com/util/post-embeds/QuoteEmbed' -import {Text} from '#/view/com/util/text/Text' import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar' import {atoms as a, useTheme} from '#/alf' +import {Text} from '#/components/Typography' +import {useSimpleVerificationState} from '#/components/verification' +import {VerificationCheck} from '#/components/verification/VerificationCheck' export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) { const t = useTheme() const {_} = useLingui() const {embed} = replyTo - const [showFull, setShowFull] = React.useState(false) + const [showFull, setShowFull] = useState(false) - const onPress = React.useCallback(() => { + const onPress = useCallback(() => { setShowFull(prev => !prev) LayoutAnimation.configureNext({ duration: 350, @@ -33,7 +35,7 @@ export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) { }) }, []) - const quoteEmbed = React.useMemo(() => { + const quoteEmbed = useMemo(() => { if ( AppBskyEmbedRecord.isView(embed) && AppBskyEmbedRecord.isViewRecord(embed.record) && @@ -50,7 +52,7 @@ export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) { return null }, [embed]) - const images = React.useMemo(() => { + const images = useMemo(() => { if (AppBskyEmbedImages.isView(embed)) { return embed.images } else if ( @@ -61,17 +63,26 @@ export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) { } }, [embed]) + const verification = useSimpleVerificationState({profile: replyTo.author}) + return ( + accessibilityHint=""> - - - {sanitizeDisplayName( - replyTo.author.displayName || sanitizeHandle(replyTo.author.handle), + + + + {sanitizeDisplayName( + replyTo.author.displayName || + sanitizeHandle(replyTo.author.handle), + )} + + {verification.showBadge && ( + + + )} - - - + + + {replyTo.text} @@ -112,7 +136,17 @@ function ComposerReplyToImages({ showFull: boolean }) { return ( - + {(images.length === 1 && ( ) } - -const styles = StyleSheet.create({ - replyToLayout: { - flexDirection: 'row', - alignItems: 'flex-start', - borderBottomWidth: StyleSheet.hairlineWidth, - paddingTop: 4, - paddingBottom: 16, - marginBottom: 12, - marginHorizontal: 16, - }, - replyToPost: { - flex: 1, - paddingLeft: 13, - paddingRight: 8, - }, - replyToBody: { - flexDirection: 'row', - gap: 10, - }, - replyToText: { - flex: 1, - flexGrow: 1, - }, - imagesContainer: { - borderRadius: 6, - overflow: 'hidden', - marginTop: 2, - height: 64, - width: 64, - }, -}) diff --git a/src/view/com/modals/EditProfile.tsx b/src/view/com/modals/EditProfile.tsx index 2b9969b546..8cc2d31ecc 100644 --- a/src/view/com/modals/EditProfile.tsx +++ b/src/view/com/modals/EditProfile.tsx @@ -8,14 +8,14 @@ import { TouchableOpacity, View, } from 'react-native' -import {Image as RNImage} from 'react-native-image-crop-picker' +import {type Image as RNImage} from 'react-native-image-crop-picker' import Animated, {FadeOut} from 'react-native-reanimated' import {LinearGradient} from 'expo-linear-gradient' -import {AppBskyActorDefs} from '@atproto/api' +import {type AppBskyActorDefs} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {MAX_DESCRIPTION, MAX_DISPLAY_NAME} from '#/lib/constants' +import {MAX_DESCRIPTION, MAX_DISPLAY_NAME, urls} from '#/lib/constants' import {usePalette} from '#/lib/hooks/usePalette' import {compressIfNeeded} from '#/lib/media/manip' import {cleanError} from '#/lib/strings/errors' @@ -30,6 +30,9 @@ import {Text} from '#/view/com/util/text/Text' import * as Toast from '#/view/com/util/Toast' import {EditableUserAvatar} from '#/view/com/util/UserAvatar' import {UserBanner} from '#/view/com/util/UserBanner' +import {Admonition} from '#/components/Admonition' +import {InlineLinkText} from '#/components/Link' +import {useSimpleVerificationState} from '#/components/verification' import {ErrorMessage} from '../util/error/ErrorMessage' const AnimatedTouchableOpacity = @@ -139,6 +142,10 @@ export function Component({ setImageError, _, ]) + const verification = useSimpleVerificationState({ + profile, + }) + const [touchedDisplayName, setTouchedDisplayName] = useState(false) return ( @@ -186,7 +193,26 @@ export function Component({ accessible={true} accessibilityLabel={_(msg`Display name`)} accessibilityHint={_(msg`Edit your display name`)} + onFocus={() => setTouchedDisplayName(true)} /> + + {verification.isVerified && + verification.role === 'default' && + touchedDisplayName && ( + + + + You are verified. You will lose your verification status + if you change your display name.{' '} + + Learn more. + + + + + )} diff --git a/src/view/com/notifications/NotificationFeedItem.tsx b/src/view/com/notifications/NotificationFeedItem.tsx index 8875ec02ea..1de0b67b3a 100644 --- a/src/view/com/notifications/NotificationFeedItem.tsx +++ b/src/view/com/notifications/NotificationFeedItem.tsx @@ -49,7 +49,7 @@ import {Post} from '#/view/com/post/Post' import {formatCount} from '#/view/com/util/numeric/format' import {TimeElapsed} from '#/view/com/util/TimeElapsed' import {PreviewableUserAvatar, UserAvatar} from '#/view/com/util/UserAvatar' -import {atoms as a, useTheme} from '#/alf' +import {atoms as a, platform, useTheme} from '#/alf' import {Button, ButtonText} from '#/components/Button' import { ChevronBottom_Stroke2_Corner0_Rounded as ChevronDownIcon, @@ -59,12 +59,15 @@ import {Heart2_Filled_Stroke2_Corner0_Rounded as HeartIconFilled} from '#/compon import {PersonPlus_Filled_Stroke2_Corner0_Rounded as PersonPlusIcon} from '#/components/icons/Person' import {Repost_Stroke2_Corner2_Rounded as RepostIcon} from '#/components/icons/Repost' import {StarterPack} from '#/components/icons/StarterPack' +import {VerifiedCheck} from '#/components/icons/VerifiedCheck' import {InlineLinkText, Link} from '#/components/Link' import * as MediaPreview from '#/components/MediaPreview' import {ProfileHoverCard} from '#/components/ProfileHoverCard' import {Notification as StarterPackCard} from '#/components/StarterPack/StarterPackCard' import {SubtleWebHover} from '#/components/SubtleWebHover' import {Text} from '#/components/Typography' +import {useSimpleVerificationState} from '#/components/verification' +import {VerificationCheck} from '#/components/verification/VerificationCheck' import * as bsky from '#/types/bsky' const MAX_AUTHORS = 5 @@ -145,6 +148,9 @@ let NotificationFeedItem = ({ const niceTimestamp = niceDate(i18n, item.notification.indexedAt) const firstAuthor = authors[0] + const firstAuthorVerification = useSimpleVerificationState({ + profile: firstAuthor.profile, + }) const firstAuthorName = sanitizeDisplayName( firstAuthor.profile.displayName || firstAuthor.profile.handle, ) @@ -186,6 +192,24 @@ let NotificationFeedItem = ({ emoji label={_(msg`Go to ${firstAuthorName}'s profile`)}> {forceLTR(firstAuthorName)} + {firstAuthorVerification.showBadge && ( + + + + )} ) const additionalAuthorsCount = authors.length - 1 @@ -366,6 +390,60 @@ let NotificationFeedItem = ({ ) + // @ts-ignore TODO + } else if (item.type === 'verified') { + a11yLabel = hasMultipleAuthors + ? _( + msg`${firstAuthorName} and ${plural(additionalAuthorsCount, { + one: `${formattedAuthorsCount} other`, + other: `${formattedAuthorsCount} others`, + })} verified you`, + ) + : _(msg`${firstAuthorName} verified you`) + notificationContent = hasMultipleAuthors ? ( + + {firstAuthorLink} and{' '} + + + {' '} + verified you + + ) : ( + {firstAuthorLink} verified you + ) + icon = + // @ts-ignore TODO + } else if (item.type === 'unverified') { + a11yLabel = hasMultipleAuthors + ? _( + msg`${firstAuthorName} and ${plural(additionalAuthorsCount, { + one: `${formattedAuthorsCount} other`, + other: `${formattedAuthorsCount} others`, + })} removed their verifications from your account`, + ) + : _(msg`${firstAuthorName} removed their verification from your account`) + notificationContent = hasMultipleAuthors ? ( + + {firstAuthorLink} and{' '} + + + {' '} + removed their verifications from your account + + ) : ( + + {firstAuthorLink} removed their verification from your account + + ) + icon = } else { return null } @@ -447,7 +525,6 @@ let NotificationFeedItem = ({ style={[ a.flex_row, a.flex_wrap, - a.pb_2xs, {paddingTop: 6}, a.self_start, a.text_md, @@ -475,7 +552,9 @@ let NotificationFeedItem = ({ {item.type === 'post-like' || item.type === 'repost' ? ( - + + + ) : null} {item.type === 'feedgen-like' && item.subjectUri ? ( {visible && authors.map(author => ( - - - - - - - - - - {sanitizeDisplayName( - author.profile.displayName || author.profile.handle, - )} - - - {sanitizeHandle(author.profile.handle, '@')} - - - - + ))} ) } +function ExpandedAuthorCard({author}: {author: Author}) { + const t = useTheme() + const {_} = useLingui() + const verification = useSimpleVerificationState({ + profile: author.profile, + }) + return ( + + + + + + + + + + {sanitizeDisplayName( + author.profile.displayName || author.profile.handle, + )} + + {verification.showBadge && ( + + + + )} + + {sanitizeHandle(author.profile.handle, '@')} + + + + + ) +} + function AdditionalPostText({post}: {post?: AppBskyFeedDefs.PostView}) { const t = useTheme() if ( @@ -761,7 +857,7 @@ function AdditionalPostText({post}: {post?: AppBskyFeedDefs.PostView}) { {text?.length > 0 && ( + style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}> {text} )} diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx index 3c8fa31edf..dfd641f666 100644 --- a/src/view/com/post-thread/PostThreadItem.tsx +++ b/src/view/com/post-thread/PostThreadItem.tsx @@ -32,6 +32,7 @@ import { type Shadow, usePostShadow, } from '#/state/cache/post-shadow' +import {useProfileShadow} from '#/state/cache/profile-shadow' import {useLanguagePrefs} from '#/state/preferences' import {type ThreadPost} from '#/state/queries/post-thread' import {useSession} from '#/state/session' @@ -62,6 +63,7 @@ import * as Prompt from '#/components/Prompt' import {RichText} from '#/components/RichText' import {SubtleWebHover} from '#/components/SubtleWebHover' import {Text} from '#/components/Typography' +import {VerificationCheckButton} from '#/components/verification/VerificationCheckButton' import {WhoCanReply} from '#/components/WhoCanReply' import * as bsky from '#/types/bsky' @@ -207,6 +209,7 @@ let PostThreadItemLoaded = ({ () => countLines(richText?.text) >= MAX_POST_LINES, ) const {currentAccount} = useSession() + const shadowedPostAuthor = useProfileShadow(post.author) const rootUri = record.reply?.root?.uri || post.uri const postHref = React.useMemo(() => { const urip = new AtUri(post.uri) @@ -329,18 +332,35 @@ let PostThreadItemLoaded = ({ type={post.author.associated?.labeler ? 'labeler' : 'user'} /> - - - {sanitizeDisplayName( - post.author.displayName || - sanitizeHandle(post.author.handle), - moderation.ui('displayName'), - )} - - + + + + {sanitizeDisplayName( + post.author.displayName || + sanitizeHandle(post.author.handle), + moderation.ui('displayName'), + )} + + + + + + + { + return v.issuer === currentAccount?.did + }) ?? [] + return ( @@ -277,6 +290,29 @@ let ProfileMenu = ({ + {verification.viewer.role === 'verifier' && + !verification.profile.isViewer && + (verification.viewer.hasIssuedVerification ? ( + verificationRemovePromptControl.open()}> + + Remove verification + + + + ) : ( + verificationCreatePromptControl.open()}> + + Verify account + + + + ))} {!isSelf && ( <> {!profile.viewer?.blocking && @@ -410,6 +446,16 @@ let ProfileMenu = ({ onConfirm={onPressShare} confirmButtonCta={_(msg`Share anyway`)} /> + + + ) } diff --git a/src/view/com/util/PostMeta.tsx b/src/view/com/util/PostMeta.tsx index 30180b889a..d5af322367 100644 --- a/src/view/com/util/PostMeta.tsx +++ b/src/view/com/util/PostMeta.tsx @@ -1,9 +1,10 @@ -import React, {memo, useCallback} from 'react' -import {StyleProp, View, ViewStyle} from 'react-native' -import {AppBskyActorDefs, ModerationDecision} from '@atproto/api' +import {memo, useCallback} from 'react' +import {type StyleProp, View, type ViewStyle} from 'react-native' +import {type AppBskyActorDefs, type ModerationDecision} from '@atproto/api' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useQueryClient} from '@tanstack/react-query' +import type React from 'react' import {makeProfileLink} from '#/lib/routes/links' import {forceLTR} from '#/lib/strings/bidi' @@ -12,11 +13,14 @@ import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeHandle} from '#/lib/strings/handles' import {niceDate} from '#/lib/strings/time' import {isAndroid} from '#/platform/detection' +import {useProfileShadow} from '#/state/cache/profile-shadow' import {precacheProfile} from '#/state/queries/profile' -import {atoms as a, useTheme, web} from '#/alf' +import {atoms as a, platform, useTheme, web} from '#/alf' import {WebOnlyInlineLinkText} from '#/components/Link' import {ProfileHoverCard} from '#/components/ProfileHoverCard' import {Text} from '#/components/Typography' +import {useSimpleVerificationState} from '#/components/verification' +import {VerificationCheck} from '#/components/verification/VerificationCheck' import {TimeElapsed} from './TimeElapsed' import {PreviewableUserAvatar} from './UserAvatar' @@ -35,20 +39,22 @@ let PostMeta = (opts: PostMetaOpts): React.ReactNode => { const t = useTheme() const {i18n, _} = useLingui() - const displayName = opts.author.displayName || opts.author.handle - const handle = opts.author.handle - const profileLink = makeProfileLink(opts.author) + const author = useProfileShadow(opts.author) + const displayName = author.displayName || author.handle + const handle = author.handle + const profileLink = makeProfileLink(author) const queryClient = useQueryClient() const onOpenAuthor = opts.onOpenAuthor const onBeforePressAuthor = useCallback(() => { - precacheProfile(queryClient, opts.author) + precacheProfile(queryClient, author) onOpenAuthor?.() - }, [queryClient, opts.author, onOpenAuthor]) + }, [queryClient, author, onOpenAuthor]) const onBeforePressPost = useCallback(() => { - precacheProfile(queryClient, opts.author) - }, [queryClient, opts.author]) + precacheProfile(queryClient, author) + }, [queryClient, author]) const timestampLabel = niceDate(i18n, opts.timestamp) + const verification = useSimpleVerificationState({profile: author}) return ( { a.flex_1, a.flex_row, a.align_center, - a.pb_2xs, + a.pb_xs, a.gap_xs, - a.z_10, + a.z_20, opts.style, ]}> {opts.showAvatar && ( )} - - - - + + + + {forceLTR( sanitizeDisplayName( displayName, opts.moderation?.ui('displayName'), ), )} - - - - + + {verification.showBadge && ( + + + + )} + {NON_BREAKING_SPACE + sanitizeHandle(handle, '@')} - - - - + + + - {!isAndroid && ( - - · - - )} - - - {({timeElapsed}) => ( - - {timeElapsed} - - )} - + + {({timeElapsed}) => ( + + {!isAndroid && ( + + ·{' '} + + )} + {timeElapsed} + + )} + + ) } diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx index e38cb217c7..d51db3960c 100644 --- a/src/view/shell/Drawer.tsx +++ b/src/view/shell/Drawer.tsx @@ -51,6 +51,8 @@ import { } from '#/components/icons/UserCircle' import {InlineLinkText} from '#/components/Link' import {Text} from '#/components/Typography' +import {useSimpleVerificationState} from '#/components/verification' +import {VerificationCheck} from '#/components/verification/VerificationCheck' const iconWidth = 26 @@ -64,6 +66,7 @@ let DrawerProfileCard = ({ const {_, i18n} = useLingui() const t = useTheme() const {data: profile} = useProfileQuery({did: account.did}) + const verification = useSimpleVerificationState({profile}) return ( + style={[a.gap_sm, a.pr_lg]}> - - {profile?.displayName || account.handle} - + + + {profile?.displayName || account.handle} + + {verification.showBadge && ( + + + + )} +