diff options
Diffstat (limited to 'src/view/com/util/moderation')
-rw-r--r-- | src/view/com/util/moderation/ContentHider.tsx | 109 | ||||
-rw-r--r-- | src/view/com/util/moderation/PostHider.tsx | 105 | ||||
-rw-r--r-- | src/view/com/util/moderation/ProfileHeaderLabels.tsx | 55 |
3 files changed, 269 insertions, 0 deletions
diff --git a/src/view/com/util/moderation/ContentHider.tsx b/src/view/com/util/moderation/ContentHider.tsx new file mode 100644 index 000000000..f65635d35 --- /dev/null +++ b/src/view/com/util/moderation/ContentHider.tsx @@ -0,0 +1,109 @@ +import React from 'react' +import { + StyleProp, + StyleSheet, + TouchableOpacity, + View, + ViewStyle, +} from 'react-native' +import {ComAtprotoLabelDefs} from '@atproto/api' +import {usePalette} from 'lib/hooks/usePalette' +import {useStores} from 'state/index' +import {Text} from '../text/Text' +import {addStyle} from 'lib/styles' + +export function ContentHider({ + testID, + isMuted, + labels, + style, + containerStyle, + children, +}: React.PropsWithChildren<{ + testID?: string + isMuted?: boolean + labels: ComAtprotoLabelDefs.Label[] | undefined + style?: StyleProp<ViewStyle> + containerStyle?: StyleProp<ViewStyle> +}>) { + const pal = usePalette('default') + const [override, setOverride] = React.useState(false) + const store = useStores() + const labelPref = store.preferences.getLabelPreference(labels) + + if (!isMuted && labelPref.pref === 'show') { + return ( + <View testID={testID} style={style}> + {children} + </View> + ) + } + + if (labelPref.pref === 'hide') { + return <></> + } + + return ( + <View style={[styles.container, pal.view, pal.border, containerStyle]}> + <View + style={[ + styles.description, + pal.viewLight, + override && styles.descriptionOpen, + ]}> + <Text type="md" style={pal.textLight}> + {isMuted ? ( + <>Post from an account you muted.</> + ) : ( + <>Warning: {labelPref.desc.title}</> + )} + </Text> + <TouchableOpacity + style={styles.showBtn} + onPress={() => setOverride(v => !v)}> + <Text type="md" style={pal.link}> + {override ? 'Hide' : 'Show'} + </Text> + </TouchableOpacity> + </View> + {override && ( + <View style={[styles.childrenContainer, pal.border]}> + <View testID={testID} style={addStyle(style, styles.child)}> + {children} + </View> + </View> + )} + </View> + ) +} + +const styles = StyleSheet.create({ + container: { + marginBottom: 10, + borderWidth: 1, + borderRadius: 12, + }, + description: { + flexDirection: 'row', + alignItems: 'center', + paddingVertical: 14, + paddingLeft: 14, + paddingRight: 18, + borderRadius: 12, + }, + descriptionOpen: { + borderBottomLeftRadius: 0, + borderBottomRightRadius: 0, + }, + icon: { + marginRight: 10, + }, + showBtn: { + marginLeft: 'auto', + }, + childrenContainer: { + paddingHorizontal: 12, + paddingTop: 8, + }, + child: {}, +}) diff --git a/src/view/com/util/moderation/PostHider.tsx b/src/view/com/util/moderation/PostHider.tsx new file mode 100644 index 000000000..bafc7aecf --- /dev/null +++ b/src/view/com/util/moderation/PostHider.tsx @@ -0,0 +1,105 @@ +import React from 'react' +import { + StyleProp, + StyleSheet, + TouchableOpacity, + View, + ViewStyle, +} from 'react-native' +import {ComAtprotoLabelDefs} from '@atproto/api' +import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' +import {usePalette} from 'lib/hooks/usePalette' +import {Link} from '../Link' +import {Text} from '../text/Text' +import {addStyle} from 'lib/styles' +import {useStores} from 'state/index' + +export function PostHider({ + testID, + href, + isMuted, + labels, + style, + children, +}: React.PropsWithChildren<{ + testID?: string + href: string + isMuted: boolean | undefined + labels: ComAtprotoLabelDefs.Label[] | undefined + style: StyleProp<ViewStyle> +}>) { + const store = useStores() + const pal = usePalette('default') + const [override, setOverride] = React.useState(false) + const bg = override ? pal.viewLight : pal.view + + const labelPref = store.preferences.getLabelPreference(labels) + if (labelPref.pref === 'hide') { + return <></> + } + + if (!isMuted) { + // NOTE: any further label enforcement should occur in ContentContainer + return ( + <Link testID={testID} style={style} href={href} noFeedback> + {children} + </Link> + ) + } + + return ( + <> + <View style={[styles.description, bg, pal.border]}> + <FontAwesomeIcon + icon={['far', 'eye-slash']} + style={[styles.icon, pal.text]} + /> + <Text type="md" style={pal.textLight}> + Post from an account you muted. + </Text> + <TouchableOpacity + style={styles.showBtn} + onPress={() => setOverride(v => !v)}> + <Text type="md" style={pal.link}> + {override ? 'Hide' : 'Show'} post + </Text> + </TouchableOpacity> + </View> + {override && ( + <View style={[styles.childrenContainer, pal.border, bg]}> + <Link + testID={testID} + style={addStyle(style, styles.child)} + href={href} + noFeedback> + {children} + </Link> + </View> + )} + </> + ) +} + +const styles = StyleSheet.create({ + description: { + flexDirection: 'row', + alignItems: 'center', + paddingVertical: 14, + paddingHorizontal: 18, + borderTopWidth: 1, + }, + icon: { + marginRight: 10, + }, + showBtn: { + marginLeft: 'auto', + }, + childrenContainer: { + paddingHorizontal: 6, + paddingBottom: 6, + }, + child: { + borderWidth: 1, + borderRadius: 12, + }, +}) diff --git a/src/view/com/util/moderation/ProfileHeaderLabels.tsx b/src/view/com/util/moderation/ProfileHeaderLabels.tsx new file mode 100644 index 000000000..e099f09a7 --- /dev/null +++ b/src/view/com/util/moderation/ProfileHeaderLabels.tsx @@ -0,0 +1,55 @@ +import React from 'react' +import {StyleSheet, View} from 'react-native' +import {ComAtprotoLabelDefs} from '@atproto/api' +import { + FontAwesomeIcon, + FontAwesomeIconStyle, +} from '@fortawesome/react-native-fontawesome' +import {Text} from '../text/Text' +import {usePalette} from 'lib/hooks/usePalette' +import {getLabelValueGroup} from 'lib/labeling/helpers' + +export function ProfileHeaderLabels({ + labels, +}: { + labels: ComAtprotoLabelDefs.Label[] | undefined +}) { + const palErr = usePalette('error') + if (!labels?.length) { + return null + } + return ( + <> + {labels.map((label, i) => { + const labelGroup = getLabelValueGroup(label?.val || '') + return ( + <View + key={`${label.val}-${i}`} + style={[styles.container, palErr.border, palErr.view]}> + <FontAwesomeIcon + icon="circle-exclamation" + style={palErr.text as FontAwesomeIconStyle} + size={20} + /> + <Text style={palErr.text}> + This account has been flagged for{' '} + {labelGroup.title.toLocaleLowerCase()}. + </Text> + </View> + ) + })} + </> + ) +} + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + alignItems: 'center', + gap: 10, + borderWidth: 1, + borderRadius: 6, + paddingHorizontal: 10, + paddingVertical: 8, + }, +}) |