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>
This commit is contained in:
@@ -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 (
|
||||
<Pressable
|
||||
style={[t.atoms.border_contrast_medium, styles.replyToLayout]}
|
||||
style={[
|
||||
a.flex_row,
|
||||
a.align_start,
|
||||
a.pt_xs,
|
||||
a.pb_lg,
|
||||
a.mb_md,
|
||||
a.mx_lg,
|
||||
a.border_b,
|
||||
t.atoms.border_contrast_medium,
|
||||
]}
|
||||
onPress={onPress}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={_(
|
||||
msg`Expand or collapse the full post you are replying to`,
|
||||
)}
|
||||
accessibilityHint={_(
|
||||
msg`Expands or collapses the full post you are replying to`,
|
||||
)}>
|
||||
accessibilityHint="">
|
||||
<PreviewableUserAvatar
|
||||
size={50}
|
||||
profile={replyTo.author}
|
||||
@@ -79,17 +90,30 @@ export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) {
|
||||
type={replyTo.author.associated?.labeler ? 'labeler' : 'user'}
|
||||
disableNavigation={true}
|
||||
/>
|
||||
<View style={styles.replyToPost}>
|
||||
<Text type="xl-medium" style={t.atoms.text} numberOfLines={1} emoji>
|
||||
{sanitizeDisplayName(
|
||||
replyTo.author.displayName || sanitizeHandle(replyTo.author.handle),
|
||||
<View style={[a.flex_1, a.pl_md, a.pr_sm, a.gap_2xs]}>
|
||||
<View style={[a.flex_row, a.align_center, a.pr_xs]}>
|
||||
<Text
|
||||
style={[a.font_bold, a.text_md, a.flex_shrink]}
|
||||
numberOfLines={1}
|
||||
emoji>
|
||||
{sanitizeDisplayName(
|
||||
replyTo.author.displayName ||
|
||||
sanitizeHandle(replyTo.author.handle),
|
||||
)}
|
||||
</Text>
|
||||
{verification.showBadge && (
|
||||
<View style={[a.pl_xs]}>
|
||||
<VerificationCheck
|
||||
width={14}
|
||||
verifier={verification.role === 'verifier'}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</Text>
|
||||
<View style={styles.replyToBody}>
|
||||
<View style={styles.replyToText}>
|
||||
</View>
|
||||
<View style={[a.flex_row, a.gap_md]}>
|
||||
<View style={[a.flex_1, a.flex_grow]}>
|
||||
<Text
|
||||
type="post-text"
|
||||
style={t.atoms.text}
|
||||
style={[a.text_md]}
|
||||
numberOfLines={!showFull ? 6 : undefined}
|
||||
emoji>
|
||||
{replyTo.text}
|
||||
@@ -112,7 +136,17 @@ function ComposerReplyToImages({
|
||||
showFull: boolean
|
||||
}) {
|
||||
return (
|
||||
<View style={[styles.imagesContainer, a.mx_xs]}>
|
||||
<View
|
||||
style={[
|
||||
a.rounded_xs,
|
||||
a.overflow_hidden,
|
||||
a.mt_2xs,
|
||||
a.mx_xs,
|
||||
{
|
||||
height: 64,
|
||||
width: 64,
|
||||
},
|
||||
]}>
|
||||
{(images.length === 1 && (
|
||||
<Image
|
||||
source={{uri: images[0].thumb}}
|
||||
@@ -196,35 +230,3 @@ function ComposerReplyToImages({
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user