mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React from 'react'
2import {StyleProp, View, ViewStyle} from 'react-native'
3import {ModerationUI} from '@atproto/api'
4import {msg, Trans} from '@lingui/macro'
5import {useLingui} from '@lingui/react'
6
7import {ADULT_CONTENT_LABELS, isJustAMute} from '#/lib/moderation'
8import {useGlobalLabelStrings} from '#/lib/moderation/useGlobalLabelStrings'
9import {getDefinition, getLabelStrings} from '#/lib/moderation/useLabelInfo'
10import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription'
11import {sanitizeDisplayName} from '#/lib/strings/display-names'
12import {useLabelDefinitions} from '#/state/preferences'
13import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
14import {Button} from '#/components/Button'
15import {
16 ModerationDetailsDialog,
17 useModerationDetailsDialogControl,
18} from '#/components/moderation/ModerationDetailsDialog'
19import {Text} from '#/components/Typography'
20
21export function ContentHider({
22 testID,
23 modui,
24 ignoreMute,
25 style,
26 childContainerStyle,
27 children,
28}: React.PropsWithChildren<{
29 testID?: string
30 modui: ModerationUI | undefined
31 ignoreMute?: boolean
32 style?: StyleProp<ViewStyle>
33 childContainerStyle?: StyleProp<ViewStyle>
34}>) {
35 const t = useTheme()
36 const {_} = useLingui()
37 const {gtMobile} = useBreakpoints()
38 const [override, setOverride] = React.useState(false)
39 const control = useModerationDetailsDialogControl()
40 const {labelDefs} = useLabelDefinitions()
41 const globalLabelStrings = useGlobalLabelStrings()
42 const {i18n} = useLingui()
43
44 const blur = modui?.blurs[0]
45 const desc = useModerationCauseDescription(blur)
46
47 const labelName = React.useMemo(() => {
48 if (!modui?.blurs || !blur) {
49 return undefined
50 }
51 if (
52 blur.type !== 'label' ||
53 (blur.type === 'label' && blur.source.type !== 'user')
54 ) {
55 return desc.name
56 }
57
58 let hasAdultContentLabel = false
59 const selfBlurNames = modui.blurs
60 .filter(cause => {
61 if (cause.type !== 'label') {
62 return false
63 }
64 if (cause.source.type !== 'user') {
65 return false
66 }
67 if (ADULT_CONTENT_LABELS.includes(cause.label.val)) {
68 if (hasAdultContentLabel) {
69 return false
70 }
71 hasAdultContentLabel = true
72 }
73 return true
74 })
75 .slice(0, 2)
76 .map(cause => {
77 if (cause.type !== 'label') {
78 return
79 }
80
81 const def = cause.labelDef || getDefinition(labelDefs, cause.label)
82 if (def.identifier === 'porn' || def.identifier === 'sexual') {
83 return _(msg`Adult Content`)
84 }
85 return getLabelStrings(i18n.locale, globalLabelStrings, def).name
86 })
87
88 if (selfBlurNames.length === 0) {
89 return desc.name
90 }
91 return [...new Set(selfBlurNames)].join(', ')
92 }, [
93 _,
94 modui?.blurs,
95 blur,
96 desc.name,
97 labelDefs,
98 i18n.locale,
99 globalLabelStrings,
100 ])
101
102 if (!blur || (ignoreMute && isJustAMute(modui))) {
103 return (
104 <View testID={testID} style={style}>
105 {children}
106 </View>
107 )
108 }
109
110 return (
111 <View testID={testID} style={[a.overflow_hidden, style]}>
112 <ModerationDetailsDialog control={control} modcause={blur} />
113
114 <Button
115 onPress={e => {
116 e.preventDefault()
117 e.stopPropagation()
118 if (!modui.noOverride) {
119 setOverride(v => !v)
120 } else {
121 control.open()
122 }
123 }}
124 label={desc.name}
125 accessibilityHint={
126 modui.noOverride
127 ? _(msg`Learn more about the moderation applied to this content.`)
128 : override
129 ? _(msg`Hide the content`)
130 : _(msg`Show the content`)
131 }>
132 {state => (
133 <View
134 style={[
135 a.flex_row,
136 a.w_full,
137 a.justify_start,
138 a.align_center,
139 a.py_md,
140 a.px_lg,
141 a.gap_xs,
142 a.rounded_sm,
143 t.atoms.bg_contrast_25,
144 gtMobile && [a.gap_sm, a.py_lg, a.mt_xs, a.px_xl],
145 (state.hovered || state.pressed) && t.atoms.bg_contrast_50,
146 ]}>
147 <desc.icon
148 size="md"
149 fill={t.atoms.text_contrast_medium.color}
150 style={{marginLeft: -2}}
151 />
152 <Text
153 style={[
154 a.flex_1,
155 a.text_left,
156 a.font_bold,
157 a.leading_snug,
158 gtMobile && [a.font_bold],
159 t.atoms.text_contrast_medium,
160 web({
161 marginBottom: 1,
162 }),
163 ]}
164 numberOfLines={2}>
165 {labelName}
166 </Text>
167 {!modui.noOverride && (
168 <Text
169 style={[
170 a.font_bold,
171 a.leading_snug,
172 gtMobile && [a.font_bold],
173 t.atoms.text_contrast_high,
174 web({
175 marginBottom: 1,
176 }),
177 ]}>
178 {override ? <Trans>Hide</Trans> : <Trans>Show</Trans>}
179 </Text>
180 )}
181 </View>
182 )}
183 </Button>
184
185 {desc.source && blur.type === 'label' && !override && (
186 <Button
187 onPress={e => {
188 e.preventDefault()
189 e.stopPropagation()
190 control.open()
191 }}
192 label={_(
193 msg`Learn more about the moderation applied to this content.`,
194 )}
195 style={[a.pt_sm]}>
196 {state => (
197 <Text
198 style={[
199 a.flex_1,
200 a.text_sm,
201 a.font_normal,
202 a.leading_snug,
203 t.atoms.text_contrast_medium,
204 a.text_left,
205 ]}>
206 {desc.sourceType === 'user' ? (
207 <Trans>Labeled by the author.</Trans>
208 ) : (
209 <Trans>Labeled by {sanitizeDisplayName(desc.source!)}.</Trans>
210 )}{' '}
211 <Text
212 style={[
213 {color: t.palette.primary_500},
214 a.text_sm,
215 state.hovered && [web({textDecoration: 'underline'})],
216 ]}>
217 <Trans>Learn more.</Trans>
218 </Text>
219 </Text>
220 )}
221 </Button>
222 )}
223
224 {override && <View style={childContainerStyle}>{children}</View>}
225 </View>
226 )
227}