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