forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {View} from 'react-native'
2import {msg} from '@lingui/macro'
3import {useLingui} from '@lingui/react'
4
5import {type Shadow} from '#/state/cache/types'
6import {atoms as a, useBreakpoints, useTheme} from '#/alf'
7import {Button} from '#/components/Button'
8import {useDialogControl} from '#/components/Dialog'
9import {useFullVerificationState} from '#/components/verification'
10import {type FullVerificationState} from '#/components/verification'
11import {VerificationCheck} from '#/components/verification/VerificationCheck'
12import {VerificationsDialog} from '#/components/verification/VerificationsDialog'
13import {VerifierDialog} from '#/components/verification/VerifierDialog'
14import {useAnalytics} from '#/analytics'
15import type * as bsky from '#/types/bsky'
16
17export function shouldShowVerificationCheckButton(
18 state: FullVerificationState,
19) {
20 let ok = false
21
22 if (state.profile.role === 'default') {
23 if (state.profile.isVerified) {
24 ok = true
25 } else if (state.profile.isViewer && state.profile.wasVerified) {
26 ok = true
27 } else if (
28 state.viewer.role === 'verifier' &&
29 state.viewer.hasIssuedVerification
30 ) {
31 ok = true
32 }
33 } else if (state.profile.role === 'verifier') {
34 if (state.profile.isViewer) {
35 ok = true
36 } else if (state.profile.isVerified) {
37 ok = true
38 }
39 }
40
41 if (
42 !state.profile.showBadge &&
43 !state.profile.isViewer &&
44 !(state.viewer.role === 'verifier' && state.viewer.hasIssuedVerification)
45 ) {
46 ok = false
47 }
48
49 return ok
50}
51
52export function VerificationCheckButton({
53 profile,
54 size,
55}: {
56 profile: Shadow<bsky.profile.AnyProfileView>
57 size: 'lg' | 'md' | 'sm'
58}) {
59 const state = useFullVerificationState({
60 profile,
61 })
62
63 if (shouldShowVerificationCheckButton(state)) {
64 return <Badge profile={profile} verificationState={state} size={size} />
65 }
66
67 return null
68}
69
70export function Badge({
71 profile,
72 verificationState: state,
73 size,
74}: {
75 profile: Shadow<bsky.profile.AnyProfileView>
76 verificationState: FullVerificationState
77 size: 'lg' | 'md' | 'sm'
78}) {
79 const t = useTheme()
80 const ax = useAnalytics()
81 const {_} = useLingui()
82 const verificationsDialogControl = useDialogControl()
83 const verifierDialogControl = useDialogControl()
84 const {gtPhone} = useBreakpoints()
85 let dimensions = 12
86 if (size === 'lg') {
87 dimensions = gtPhone ? 20 : 18
88 } else if (size === 'md') {
89 dimensions = 14
90 }
91
92 const verifiedByHidden = !state.profile.showBadge && state.profile.isViewer
93
94 return (
95 <>
96 <Button
97 label={
98 state.profile.isViewer
99 ? _(msg`View your verifications`)
100 : _(msg`View this user's verifications`)
101 }
102 hitSlop={20}
103 onPress={evt => {
104 evt.preventDefault()
105 ax.metric('verification:badge:click', {})
106 if (state.profile.role === 'verifier') {
107 verifierDialogControl.open()
108 } else {
109 verificationsDialogControl.open()
110 }
111 }}>
112 {({hovered}) => (
113 <View
114 style={[
115 a.justify_end,
116 a.align_end,
117 a.transition_transform,
118 {
119 width: dimensions,
120 height: dimensions,
121 transform: [
122 {
123 scale: hovered ? 1.1 : 1,
124 },
125 ],
126 },
127 ]}>
128 <VerificationCheck
129 width={dimensions}
130 fill={
131 verifiedByHidden
132 ? t.atoms.bg_contrast_100.backgroundColor
133 : state.profile.isVerified
134 ? t.palette.primary_500
135 : t.atoms.bg_contrast_100.backgroundColor
136 }
137 verifier={state.profile.role === 'verifier'}
138 />
139 </View>
140 )}
141 </Button>
142
143 <VerificationsDialog
144 control={verificationsDialogControl}
145 profile={profile}
146 verificationState={state}
147 />
148
149 <VerifierDialog
150 control={verifierDialogControl}
151 profile={profile}
152 verificationState={state}
153 />
154 </>
155 )
156}