about summary refs log tree commit diff
path: root/src/components/dialogs
diff options
context:
space:
mode:
authorEric Bailey <git@esb.lol>2025-04-18 21:15:32 -0500
committerGitHub <noreply@github.com>2025-04-18 19:15:32 -0700
commit0ac15920a477a5c8090fd2b929b36ac0b6e02c34 (patch)
treedebd067ccc0f3f5f814d8ec10082e41034d47c7c /src/components/dialogs
parentf1e44ee12e0ccde71e616121708e70462351f068 (diff)
downloadvoidsky-0ac15920a477a5c8090fd2b929b36ac0b6e02c34.tar.zst
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 <mozzius@protonmail.com>
Co-authored-by: Paul Frazee <pfrazee@gmail.com>
Diffstat (limited to 'src/components/dialogs')
-rw-r--r--src/components/dialogs/nuxs/InitialVerificationAnnouncement.tsx194
-rw-r--r--src/components/dialogs/nuxs/index.tsx17
2 files changed, 207 insertions, 4 deletions
diff --git a/src/components/dialogs/nuxs/InitialVerificationAnnouncement.tsx b/src/components/dialogs/nuxs/InitialVerificationAnnouncement.tsx
new file mode 100644
index 000000000..fb7550043
--- /dev/null
+++ b/src/components/dialogs/nuxs/InitialVerificationAnnouncement.tsx
@@ -0,0 +1,194 @@
+import {useCallback} from 'react'
+import {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 {logger} from '#/logger'
+import {isNative} from '#/platform/detection'
+import {atoms as a, useBreakpoints, useTheme} from '#/alf'
+import {Button, ButtonText} from '#/components/Button'
+import * as Dialog from '#/components/Dialog'
+import {useNuxDialogContext} from '#/components/dialogs/nuxs'
+import {Sparkle_Stroke2_Corner0_Rounded as SparkleIcon} from '#/components/icons/Sparkle'
+import {VerifierCheck} from '#/components/icons/VerifierCheck'
+import {Link} from '#/components/Link'
+import {Span, Text} from '#/components/Typography'
+
+export function InitialVerificationAnnouncement() {
+  const t = useTheme()
+  const {_} = useLingui()
+  const {gtMobile} = useBreakpoints()
+  const nuxDialogs = useNuxDialogContext()
+  const control = Dialog.useDialogControl()
+
+  Dialog.useAutoOpen(control)
+
+  const onClose = useCallback(() => {
+    nuxDialogs.dismissActiveNux()
+  }, [nuxDialogs])
+
+  return (
+    <Dialog.Outer control={control} onClose={onClose}>
+      <Dialog.Handle />
+
+      <Dialog.ScrollableInner
+        label={_(msg`Announcing verification on Bluesky`)}
+        style={[
+          gtMobile ? {width: 'auto', maxWidth: 400, minWidth: 200} : a.w_full,
+        ]}>
+        <View style={[a.align_start, a.gap_xl]}>
+          <View
+            style={[
+              a.pl_sm,
+              a.pr_md,
+              a.py_sm,
+              a.rounded_full,
+              a.flex_row,
+              a.align_center,
+              a.gap_xs,
+              {
+                backgroundColor: t.palette.primary_25,
+              },
+            ]}>
+            <SparkleIcon fill={t.palette.primary_700} size="sm" />
+            <Text
+              style={[
+                a.font_bold,
+                {
+                  color: t.palette.primary_700,
+                },
+              ]}>
+              <Trans>New Feature</Trans>
+            </Text>
+          </View>
+
+          <View
+            style={[
+              a.w_full,
+              a.rounded_md,
+              a.overflow_hidden,
+              t.atoms.bg_contrast_25,
+              {minHeight: 100},
+            ]}>
+            <Image
+              accessibilityIgnoresInvertColors
+              source={require('../../../../assets/images/initial_verification_announcement_1.png')}
+              style={[
+                {
+                  aspectRatio: 353 / 160,
+                },
+              ]}
+              alt={_(
+                msg`An illustration showing that Bluesky selects trusted verifiers, and trusted verifiers in turn verify individual user accounts.`,
+              )}
+            />
+          </View>
+
+          <View style={[a.gap_xs]}>
+            <Text style={[a.text_2xl, a.font_bold, a.leading_snug]}>
+              <Trans>A new form of verification</Trans>
+            </Text>
+            <Text style={[a.leading_snug, a.text_md]}>
+              <Trans>
+                We’re introducing a new layer of verification on Bluesky — an
+                easy-to-see checkmark.
+              </Trans>
+            </Text>
+          </View>
+
+          <View
+            style={[
+              a.w_full,
+              a.rounded_md,
+              a.overflow_hidden,
+              t.atoms.bg_contrast_25,
+              {minHeight: 100},
+            ]}>
+            <Image
+              accessibilityIgnoresInvertColors
+              source={require('../../../../assets/images/initial_verification_announcement_2.png')}
+              style={[
+                {
+                  aspectRatio: 353 / 196,
+                },
+              ]}
+              alt={_(
+                msg`An mockup of a iPhone showing the Bluesky app open to the profile of a verified user with a blue checkmark next to their display name.`,
+              )}
+            />
+          </View>
+
+          <View style={[a.gap_sm]}>
+            <View style={[a.flex_row, a.align_center, a.gap_xs]}>
+              <VerifierCheck width={14} />
+              <Text style={[a.text_lg, a.font_bold, a.leading_snug]}>
+                <Trans>Who can verify?</Trans>
+              </Text>
+            </View>
+            <View style={[a.gap_sm]}>
+              <Text style={[a.leading_snug, a.text_md]}>
+                <Trans>
+                  Bluesky will proactively verify notable and authentic
+                  accounts.
+                </Trans>
+              </Text>
+              <Text style={[a.leading_snug, a.text_md]}>
+                <Trans>
+                  Trust emerges from relationships, communities, and shared
+                  context, so we’re also enabling{' '}
+                  <Span style={[a.font_bold]}>trusted verifiers</Span>:
+                  organizations that can directly issue verification.
+                </Trans>
+              </Text>
+              <Text style={[a.leading_snug, a.text_md]}>
+                <Trans>
+                  When you tap on a check, you’ll see which organizations have
+                  granted verification.
+                </Trans>
+              </Text>
+            </View>
+          </View>
+
+          <View style={[a.w_full, a.gap_md]}>
+            <Link
+              overridePresentation
+              to={urls.website.blog.initialVerificationAnnouncement}
+              label={_(msg`Read blog post`)}
+              size="small"
+              variant="solid"
+              color="primary"
+              style={[a.justify_center, a.w_full]}
+              onPress={() => {
+                logger.metric('verification:learn-more', {
+                  location: 'initialAnnouncementeNux',
+                })
+              }}>
+              <ButtonText>
+                <Trans>Read blog post</Trans>
+              </ButtonText>
+            </Link>
+            {isNative && (
+              <Button
+                label={_(msg`Close`)}
+                size="small"
+                variant="solid"
+                color="secondary"
+                style={[a.justify_center, a.w_full]}
+                onPress={() => {
+                  control.close()
+                }}>
+                <ButtonText>
+                  <Trans>Close</Trans>
+                </ButtonText>
+              </Button>
+            )}
+          </View>
+        </View>
+
+        <Dialog.Close />
+      </Dialog.ScrollableInner>
+    </Dialog.Outer>
+  )
+}
diff --git a/src/components/dialogs/nuxs/index.tsx b/src/components/dialogs/nuxs/index.tsx
index 10cae887b..c8c539b85 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<Context>({
   activeNux: undefined,
@@ -163,6 +169,9 @@ function Inner({
   return (
     <Context.Provider value={ctx}>
       {/*For example, activeNux === Nux.NeueTypography && <NeueTypography />*/}
+      {activeNux === Nux.InitialVerificationAnnouncement && (
+        <InitialVerificationAnnouncement />
+      )}
     </Context.Provider>
   )
 }