forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import React, {type ComponentProps} from 'react'
2import {
3 Pressable,
4 type StyleProp,
5 StyleSheet,
6 View,
7 type ViewStyle,
8} from 'react-native'
9import {
10 type AppBskyActorDefs,
11 type ModerationCause,
12 type ModerationUI,
13} from '@atproto/api'
14import {msg, Trans} from '@lingui/macro'
15import {useLingui} from '@lingui/react'
16import {useQueryClient} from '@tanstack/react-query'
17
18import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription'
19import {addStyle} from '#/lib/styles'
20import {precacheProfile} from '#/state/queries/profile'
21// import {Link} from '#/components/Link' TODO this imposes some styles that screw things up
22import {Link} from '#/view/com/util/Link'
23import {atoms as a, useTheme} from '#/alf'
24import {
25 ModerationDetailsDialog,
26 useModerationDetailsDialogControl,
27} from '#/components/moderation/ModerationDetailsDialog'
28import {Text} from '#/components/Typography'
29
30interface Props extends ComponentProps<typeof Link> {
31 disabled: boolean
32 iconSize: number
33 iconStyles: StyleProp<ViewStyle>
34 modui: ModerationUI
35 profile: AppBskyActorDefs.ProfileViewBasic
36 interpretFilterAsBlur?: boolean
37 hiderStyle?: StyleProp<ViewStyle>
38}
39
40export function PostHider({
41 testID,
42 href,
43 disabled,
44 modui,
45 style,
46 hiderStyle,
47 children,
48 iconSize,
49 iconStyles,
50 profile,
51 interpretFilterAsBlur,
52 ...props
53}: Props) {
54 const queryClient = useQueryClient()
55 const t = useTheme()
56 const {_} = useLingui()
57 const [override, setOverride] = React.useState(false)
58 const control = useModerationDetailsDialogControl()
59 const blur =
60 modui.blurs[0] ||
61 (interpretFilterAsBlur ? getBlurrableFilter(modui) : undefined)
62 const desc = useModerationCauseDescription(blur)
63
64 const onBeforePress = React.useCallback(() => {
65 precacheProfile(queryClient, profile)
66 }, [queryClient, profile])
67
68 if (!blur || (disabled && !modui.noOverride)) {
69 return (
70 <Link
71 testID={testID}
72 style={style}
73 href={href}
74 accessible={false}
75 onBeforePress={onBeforePress}
76 {...props}>
77 {children}
78 </Link>
79 )
80 }
81
82 return !override ? (
83 <Pressable
84 onPress={() => {
85 if (!modui.noOverride) {
86 setOverride(v => !v)
87 }
88 }}
89 accessibilityRole="button"
90 accessibilityHint={
91 override ? _(msg`Hides the content`) : _(msg`Shows the content`)
92 }
93 accessibilityLabel=""
94 style={[
95 a.flex_row,
96 a.align_center,
97 a.gap_sm,
98 a.py_md,
99 {
100 paddingLeft: 6,
101 paddingRight: 18,
102 },
103 override ? {paddingBottom: 0} : undefined,
104 t.atoms.bg,
105 hiderStyle,
106 ]}>
107 <ModerationDetailsDialog control={control} modcause={blur} />
108 <Pressable
109 onPress={() => {
110 control.open()
111 }}
112 accessibilityRole="button"
113 accessibilityLabel={_(msg`Learn more about this warning`)}
114 accessibilityHint="">
115 <View
116 style={[
117 t.atoms.bg_contrast_25,
118 a.align_center,
119 a.justify_center,
120 {
121 width: iconSize,
122 height: iconSize,
123 borderRadius: iconSize,
124 },
125 iconStyles,
126 ]}>
127 <desc.icon size="sm" fill={t.atoms.text_contrast_medium.color} />
128 </View>
129 </Pressable>
130 <Text
131 style={[t.atoms.text_contrast_medium, a.flex_1, a.leading_snug]}
132 numberOfLines={1}>
133 {desc.name}
134 </Text>
135 {!modui.noOverride && (
136 <Text style={[{color: t.palette.primary_500}]}>
137 {override ? <Trans>Hide</Trans> : <Trans>Show</Trans>}
138 </Text>
139 )}
140 </Pressable>
141 ) : (
142 <Link
143 testID={testID}
144 style={addStyle(style, styles.child)}
145 href={href}
146 accessible={false}
147 {...props}>
148 {children}
149 </Link>
150 )
151}
152
153function getBlurrableFilter(modui: ModerationUI): ModerationCause | undefined {
154 // moderation causes get "downgraded" when they originate from embedded content
155 // a downgraded cause should *only* drive filtering in feeds, so we want to look
156 // for filters that arent downgraded
157 return modui.filters.find(filter => !filter.downgraded)
158}
159
160const styles = StyleSheet.create({
161 child: {
162 borderWidth: 0,
163 borderTopWidth: 0,
164 borderRadius: 8,
165 },
166})