diff options
Diffstat (limited to 'src/view/com')
-rw-r--r-- | src/view/com/modals/ContentFilteringSettings.tsx | 44 | ||||
-rw-r--r-- | src/view/com/post-thread/PostThreadItem.tsx | 9 | ||||
-rw-r--r-- | src/view/com/post/Post.tsx | 5 | ||||
-rw-r--r-- | src/view/com/posts/FeedItem.tsx | 5 | ||||
-rw-r--r-- | src/view/com/util/moderation/ContentHider.tsx | 41 | ||||
-rw-r--r-- | src/view/com/util/moderation/ImageHider.tsx | 128 |
6 files changed, 197 insertions, 35 deletions
diff --git a/src/view/com/modals/ContentFilteringSettings.tsx b/src/view/com/modals/ContentFilteringSettings.tsx index cfba2575a..30b465562 100644 --- a/src/view/com/modals/ContentFilteringSettings.tsx +++ b/src/view/com/modals/ContentFilteringSettings.tsx @@ -24,10 +24,22 @@ export function Component({}: {}) { <View testID="contentModerationModal" style={[pal.view, styles.container]}> <Text style={[pal.text, styles.title]}>Content Moderation</Text> <ScrollView style={styles.scrollContainer}> - <ContentLabelPref group="nsfw" /> - <ContentLabelPref group="nudity" /> - <ContentLabelPref group="suggestive" /> - <ContentLabelPref group="gore" /> + <ContentLabelPref + group="nsfw" + disabled={!store.preferences.adultContentEnabled} + /> + <ContentLabelPref + group="nudity" + disabled={!store.preferences.adultContentEnabled} + /> + <ContentLabelPref + group="suggestive" + disabled={!store.preferences.adultContentEnabled} + /> + <ContentLabelPref + group="gore" + disabled={!store.preferences.adultContentEnabled} + /> <ContentLabelPref group="hate" /> <ContentLabelPref group="spam" /> <ContentLabelPref group="impersonation" /> @@ -55,7 +67,13 @@ export function Component({}: {}) { // TODO: Refactor this component to pass labels down to each tab const ContentLabelPref = observer( - ({group}: {group: keyof typeof CONFIGURABLE_LABEL_GROUPS}) => { + ({ + group, + disabled, + }: { + group: keyof typeof CONFIGURABLE_LABEL_GROUPS + disabled?: boolean + }) => { const store = useStores() const pal = usePalette('default') return ( @@ -70,11 +88,17 @@ const ContentLabelPref = observer( </Text> )} </View> - <SelectGroup - current={store.preferences.contentLabels[group]} - onChange={v => store.preferences.setContentLabelPref(group, v)} - group={group} - /> + {disabled ? ( + <Text type="sm-bold" style={pal.textLight}> + Hide + </Text> + ) : ( + <SelectGroup + current={store.preferences.contentLabels[group]} + onChange={v => store.preferences.setContentLabelPref(group, v)} + group={group} + /> + )} </View> ) }, diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx index d657c92c3..563a3ead6 100644 --- a/src/view/com/post-thread/PostThreadItem.tsx +++ b/src/view/com/post-thread/PostThreadItem.tsx @@ -24,6 +24,7 @@ import {PostEmbeds} from '../util/post-embeds' import {PostCtrls} from '../util/PostCtrls' import {PostHider} from '../util/moderation/PostHider' import {ContentHider} from '../util/moderation/ContentHider' +import {ImageHider} from '../util/moderation/ImageHider' import {ErrorMessage} from '../util/error/ErrorMessage' import {usePalette} from 'lib/hooks/usePalette' import {formatCount} from '../util/numeric/format' @@ -234,7 +235,9 @@ export const PostThreadItem = observer(function PostThreadItem({ /> </View> ) : undefined} - <PostEmbeds embed={item.post.embed} style={s.mb10} /> + <ImageHider moderation={item.moderation.view} style={s.mb10}> + <PostEmbeds embed={item.post.embed} style={s.mb10} /> + </ImageHider> </ContentHider> <View style={[s.mt2, s.mb10]}> <Text style={pal.textLight}>{niceDate(item.post.indexedAt)}</Text> @@ -366,7 +369,9 @@ export const PostThreadItem = observer(function PostThreadItem({ /> </View> ) : undefined} - <PostEmbeds embed={item.post.embed} style={s.mb10} /> + <ImageHider style={s.mb10} moderation={item.moderation.thread}> + <PostEmbeds embed={item.post.embed} style={s.mb10} /> + </ImageHider> </ContentHider> <PostCtrls itemUri={itemUri} diff --git a/src/view/com/post/Post.tsx b/src/view/com/post/Post.tsx index af78a951b..90698ab31 100644 --- a/src/view/com/post/Post.tsx +++ b/src/view/com/post/Post.tsx @@ -23,6 +23,7 @@ import {PostEmbeds} from '../util/post-embeds' import {PostCtrls} from '../util/PostCtrls' import {PostHider} from '../util/moderation/PostHider' import {ContentHider} from '../util/moderation/ContentHider' +import {ImageHider} from '../util/moderation/ImageHider' import {Text} from '../util/text/Text' import {RichText} from '../util/text/RichText' import * as Toast from '../util/Toast' @@ -258,7 +259,9 @@ const PostLoaded = observer( /> </View> ) : undefined} - <PostEmbeds embed={item.post.embed} style={s.mb10} /> + <ImageHider moderation={item.moderation.list} style={s.mb10}> + <PostEmbeds embed={item.post.embed} style={s.mb10} /> + </ImageHider> </ContentHider> <PostCtrls itemUri={itemUri} diff --git a/src/view/com/posts/FeedItem.tsx b/src/view/com/posts/FeedItem.tsx index 10fc775c5..ff1f46db1 100644 --- a/src/view/com/posts/FeedItem.tsx +++ b/src/view/com/posts/FeedItem.tsx @@ -16,6 +16,7 @@ import {PostCtrls} from '../util/PostCtrls' import {PostEmbeds} from '../util/post-embeds' import {PostHider} from '../util/moderation/PostHider' import {ContentHider} from '../util/moderation/ContentHider' +import {ImageHider} from '../util/moderation/ImageHider' import {RichText} from '../util/text/RichText' import * as Toast from '../util/Toast' import {UserAvatar} from '../util/UserAvatar' @@ -243,7 +244,9 @@ export const FeedItem = observer(function ({ /> </View> ) : undefined} - <PostEmbeds embed={item.post.embed} style={styles.embed} /> + <ImageHider moderation={item.moderation.list} style={styles.embed}> + <PostEmbeds embed={item.post.embed} style={styles.embed} /> + </ImageHider> </ContentHider> <PostCtrls style={styles.ctrls} diff --git a/src/view/com/util/moderation/ContentHider.tsx b/src/view/com/util/moderation/ContentHider.tsx index 0f3e47d61..ac5c8395d 100644 --- a/src/view/com/util/moderation/ContentHider.tsx +++ b/src/view/com/util/moderation/ContentHider.tsx @@ -1,11 +1,5 @@ import React from 'react' -import { - StyleProp, - StyleSheet, - TouchableOpacity, - View, - ViewStyle, -} from 'react-native' +import {Pressable, StyleProp, StyleSheet, View, ViewStyle} from 'react-native' import {usePalette} from 'lib/hooks/usePalette' import {Text} from '../text/Text' import {addStyle} from 'lib/styles' @@ -25,6 +19,12 @@ export function ContentHider({ }>) { const pal = usePalette('default') const [override, setOverride] = React.useState(false) + const onPressShow = React.useCallback(() => { + setOverride(true) + }, [setOverride]) + const onPressHide = React.useCallback(() => { + setOverride(false) + }, [setOverride]) if ( moderation.behavior === ModerationBehaviorCode.Show || @@ -44,7 +44,15 @@ export function ContentHider({ return ( <View style={[styles.container, pal.view, pal.border, containerStyle]}> - <View + <Pressable + onPress={override ? onPressHide : onPressShow} + accessibilityLabel={override ? 'Hide post' : 'Show post'} + // TODO: The text labelling should be split up so controls have unique roles + accessibilityHint={ + override + ? 'Re-hide post' + : 'Shows post hidden based on your moderation settings' + } style={[ styles.description, pal.viewLight, @@ -53,21 +61,12 @@ export function ContentHider({ <Text type="md" style={pal.textLight}> {moderation.reason || 'Content warning'} </Text> - <TouchableOpacity - style={styles.showBtn} - onPress={() => setOverride(v => !v)} - accessibilityLabel={override ? 'Hide post' : 'Show post'} - // TODO: The text labelling should be split up so controls have unique roles - accessibilityHint={ - override - ? 'Re-hide post' - : 'Shows post hidden based on your moderation settings' - }> - <Text type="md" style={pal.link}> + <View style={styles.showBtn}> + <Text type="md-medium" style={pal.link}> {override ? 'Hide' : 'Show'} </Text> - </TouchableOpacity> - </View> + </View> + </Pressable> {override && ( <View style={[styles.childrenContainer, pal.border]}> <View testID={testID} style={addStyle(style, styles.child)}> diff --git a/src/view/com/util/moderation/ImageHider.tsx b/src/view/com/util/moderation/ImageHider.tsx new file mode 100644 index 000000000..b42c6397d --- /dev/null +++ b/src/view/com/util/moderation/ImageHider.tsx @@ -0,0 +1,128 @@ +import React from 'react' +import {Pressable, StyleProp, StyleSheet, View, ViewStyle} from 'react-native' +import {usePalette} from 'lib/hooks/usePalette' +import {Text} from '../text/Text' +import {BlurView} from '../BlurView' +import {ModerationBehavior, ModerationBehaviorCode} from 'lib/labeling/types' +import {isAndroid} from 'platform/detection' + +export function ImageHider({ + testID, + moderation, + style, + containerStyle, + children, +}: React.PropsWithChildren<{ + testID?: string + moderation: ModerationBehavior + style?: StyleProp<ViewStyle> + containerStyle?: StyleProp<ViewStyle> +}>) { + const pal = usePalette('default') + const [override, setOverride] = React.useState(false) + const onPressShow = React.useCallback(() => { + setOverride(true) + }, [setOverride]) + const onPressHide = React.useCallback(() => { + setOverride(false) + }, [setOverride]) + + if (moderation.behavior !== ModerationBehaviorCode.WarnImages) { + return ( + <View testID={testID} style={style}> + {children} + </View> + ) + } + + if (moderation.behavior === ModerationBehaviorCode.Hide) { + return null + } + + return ( + <View style={[styles.container, containerStyle]}> + <View testID={testID} style={style}> + {children} + </View> + {override ? ( + <Pressable + onPress={onPressHide} + style={[styles.hideBtn, pal.view]} + accessibilityLabel="Hide image" + accessibilityHint="Rehides the image"> + <Text type="xl-bold" style={pal.link}> + Hide + </Text> + </Pressable> + ) : ( + <> + {isAndroid ? ( + /* android has an issue that breaks the blurview */ + /* see https://github.com/Kureev/react-native-blur/issues/486 */ + <View style={[pal.viewLight, styles.overlay, styles.coverView]} /> + ) : ( + <BlurView + style={[styles.overlay, styles.blurView]} + blurType="light" + blurAmount={100} + reducedTransparencyFallbackColor="white" + /> + )} + <View style={[styles.overlay, styles.info]}> + <Pressable + onPress={onPressShow} + style={[styles.showBtn, pal.view]} + accessibilityLabel="Show image" + accessibilityHint="Shows image hidden based on your moderation settings"> + <Text type="xl" style={pal.text}> + {moderation.reason || 'Content warning'} + </Text> + <Text type="xl-bold" style={pal.link}> + Show + </Text> + </Pressable> + </View> + </> + )} + </View> + ) +} + +const styles = StyleSheet.create({ + container: { + position: 'relative', + marginBottom: 10, + }, + overlay: { + position: 'absolute', + left: 0, + top: 0, + right: 0, + bottom: 0, + }, + blurView: { + borderRadius: 8, + }, + coverView: { + borderRadius: 8, + }, + info: { + justifyContent: 'center', + alignItems: 'center', + }, + showBtn: { + flexDirection: 'row', + gap: 8, + paddingHorizontal: 18, + paddingVertical: 14, + borderRadius: 24, + }, + hideBtn: { + position: 'absolute', + left: 8, + bottom: 20, + paddingHorizontal: 8, + paddingVertical: 6, + borderRadius: 8, + }, +}) |