From 0ac67c4d55791330733b3320299bededa630bb40 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Wed, 12 Apr 2023 12:07:24 -0700 Subject: [PATCH] Improve label rendering to give more context to users when appropriate --- src/view/com/post-thread/PostThreadItem.tsx | 42 ++- src/view/com/post/Post.tsx | 323 ++++++++++-------- src/view/com/posts/FeedItem.tsx | 34 +- .../ContentHider.tsx} | 19 +- .../PostHider.tsx} | 31 +- 5 files changed, 253 insertions(+), 196 deletions(-) rename src/view/com/util/{ContentContainer.tsx => moderation/ContentHider.tsx} (88%) rename src/view/com/util/{PostContainer.tsx => moderation/PostHider.tsx} (87%) diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx index 9b2c463e84..f37ece5dfe 100644 --- a/src/view/com/post-thread/PostThreadItem.tsx +++ b/src/view/com/post-thread/PostThreadItem.tsx @@ -22,8 +22,8 @@ import {useStores} from 'state/index' import {PostMeta} from '../util/PostMeta' import {PostEmbeds} from '../util/post-embeds' import {PostCtrls} from '../util/PostCtrls' -import {PostContainer} from '../util/PostContainer' -import {ContentContainer} from '../util/ContentContainer' +import {PostHider} from '../util/moderation/PostHider' +import {ContentHider} from '../util/moderation/ContentHider' import {ErrorMessage} from '../util/error/ErrorMessage' import {usePalette} from 'lib/hooks/usePalette' @@ -194,7 +194,7 @@ export const PostThreadItem = observer(function PostThreadItem({ - {item.richText?.text ? ( @@ -211,7 +211,7 @@ export const PostThreadItem = observer(function PostThreadItem({ ) : undefined} - + {item._isHighlightedPost && hasEngagement ? ( {item.post.repostCount ? ( @@ -279,7 +279,7 @@ export const PostThreadItem = observer(function PostThreadItem({ } else { return ( <> - - {item.richText?.text ? ( - - - - ) : undefined} - + + {item.richText?.text ? ( + + + + ) : undefined} + + - + {item._hasMore ? ( { - store.shell.openComposer({ - replyTo: { - uri: item.post.uri, - cid: item.post.cid, - text: record.text as string, - author: { - handle: item.post.author.handle, - displayName: item.post.author.displayName, - avatar: item.post.author.avatar, - }, - }, - }) - } - const onPressToggleRepost = () => { - return item - .toggleRepost() - .catch(e => store.log.error('Failed to toggle repost', e)) - } - const onPressToggleLike = () => { - return item - .toggleLike() - .catch(e => store.log.error('Failed to toggle like', e)) - } - const onCopyPostText = () => { - Clipboard.setString(record.text) - Toast.show('Copied to clipboard') - } - const onOpenTranslate = () => { - Linking.openURL( - encodeURI(`https://translate.google.com/#auto|en|${record?.text || ''}`), - ) - } - const onDeletePost = () => { - item.delete().then( - () => { - setDeleted(true) - Toast.show('Post deleted') - }, - e => { - store.log.error('Failed to delete post', e) - Toast.show('Failed to delete post, please try again') - }, - ) - } return ( - - {showReplyLine && } - - - - - - - - - {replyAuthorDid !== '' && ( - - - - Reply to - - - - )} - {item.richText?.text ? ( - - - - ) : undefined} - - - - - + ) }) +const PostLoaded = observer( + ({ + item, + record, + setDeleted, + showReplyLine, + style, + }: { + item: PostThreadItemModel + record: FeedPost.Record + setDeleted: (v: boolean) => void + showReplyLine?: boolean + style?: StyleProp + }) => { + const pal = usePalette('default') + const store = useStores() + + const itemUri = item.post.uri + const itemCid = item.post.cid + const itemUrip = new AtUri(item.post.uri) + const itemHref = `/profile/${item.post.author.handle}/post/${itemUrip.rkey}` + const itemTitle = `Post by ${item.post.author.handle}` + const authorHref = `/profile/${item.post.author.handle}` + const authorTitle = item.post.author.handle + let replyAuthorDid = '' + if (record.reply) { + const urip = new AtUri(record.reply.parent?.uri || record.reply.root.uri) + replyAuthorDid = urip.hostname + } + const onPressReply = React.useCallback(() => { + store.shell.openComposer({ + replyTo: { + uri: item.post.uri, + cid: item.post.cid, + text: record.text as string, + author: { + handle: item.post.author.handle, + displayName: item.post.author.displayName, + avatar: item.post.author.avatar, + }, + }, + }) + }, [store, item, record]) + + const onPressToggleRepost = React.useCallback(() => { + return item + .toggleRepost() + .catch(e => store.log.error('Failed to toggle repost', e)) + }, [item, store]) + + const onPressToggleLike = React.useCallback(() => { + return item + .toggleLike() + .catch(e => store.log.error('Failed to toggle like', e)) + }, [item, store]) + + const onCopyPostText = React.useCallback(() => { + Clipboard.setString(record.text) + Toast.show('Copied to clipboard') + }, [record]) + + const onOpenTranslate = React.useCallback(() => { + Linking.openURL( + encodeURI( + `https://translate.google.com/#auto|en|${record?.text || ''}`, + ), + ) + }, [record]) + + const onDeletePost = React.useCallback(() => { + item.delete().then( + () => { + setDeleted(true) + Toast.show('Post deleted') + }, + e => { + store.log.error('Failed to delete post', e) + Toast.show('Failed to delete post, please try again') + }, + ) + }, [item, setDeleted, store]) + + return ( + + {showReplyLine && } + + + + + + + + + {replyAuthorDid !== '' && ( + + + + Reply to + + + + )} + + {item.richText?.text ? ( + + + + ) : undefined} + + + + + + + ) + }, +) + const styles = StyleSheet.create({ outer: { padding: 10, @@ -259,4 +303,7 @@ const styles = StyleSheet.create({ borderLeftWidth: 2, borderLeftColor: colors.gray2, }, + contentHider: { + marginTop: 4, + }, }) diff --git a/src/view/com/posts/FeedItem.tsx b/src/view/com/posts/FeedItem.tsx index 2d9289a395..e6c58f7c34 100644 --- a/src/view/com/posts/FeedItem.tsx +++ b/src/view/com/posts/FeedItem.tsx @@ -14,7 +14,8 @@ import {UserInfoText} from '../util/UserInfoText' import {PostMeta} from '../util/PostMeta' import {PostCtrls} from '../util/PostCtrls' import {PostEmbeds} from '../util/post-embeds' -import {PostContainer} from '../util/PostContainer' +import {PostHider} from '../util/moderation/PostHider' +import {ContentHider} from '../util/moderation/ContentHider' import {RichText} from '../util/text/RichText' import * as Toast from '../util/Toast' import {UserAvatar} from '../util/UserAvatar' @@ -132,7 +133,7 @@ export const FeedItem = observer(function ({ ] return ( - )} - {item.richText?.text ? ( - - - - ) : undefined} - + + {item.richText?.text ? ( + + + + ) : undefined} + + - + ) }) @@ -322,6 +327,9 @@ const styles = StyleSheet.create({ flexWrap: 'wrap', paddingBottom: 4, }, + contentHider: { + marginTop: 4, + }, embed: { marginBottom: 6, }, diff --git a/src/view/com/util/ContentContainer.tsx b/src/view/com/util/moderation/ContentHider.tsx similarity index 88% rename from src/view/com/util/ContentContainer.tsx rename to src/view/com/util/moderation/ContentHider.tsx index 85d85037f8..e9749efe75 100644 --- a/src/view/com/util/ContentContainer.tsx +++ b/src/view/com/util/moderation/ContentHider.tsx @@ -9,21 +9,23 @@ import { import {ComAtprotoLabelDefs} from '@atproto/api' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {usePalette} from 'lib/hooks/usePalette' -import {Text} from './text/Text' +import {Text} from '../text/Text' import {getLabelValueGroup} from 'lib/labeling/helpers' import {addStyle} from 'lib/styles' -export function ContentContainer({ +export function ContentHider({ testID, isMuted, labels, style, + containerStyle, children, }: React.PropsWithChildren<{ testID?: string - isMuted: boolean + isMuted?: boolean labels: ComAtprotoLabelDefs.Label[] | undefined style?: StyleProp + containerStyle?: StyleProp }>) { const pal = usePalette('default') const [override, setOverride] = React.useState(false) @@ -43,17 +45,13 @@ export function ContentContainer({ } return ( - + - {isMuted ? ( <>Post from an account you muted. @@ -92,7 +90,8 @@ const styles = StyleSheet.create({ flexDirection: 'row', alignItems: 'center', paddingVertical: 14, - paddingHorizontal: 18, + paddingLeft: 14, + paddingRight: 18, borderRadius: 12, }, descriptionOpen: { @@ -106,7 +105,7 @@ const styles = StyleSheet.create({ marginLeft: 'auto', }, childrenContainer: { - paddingHorizontal: 8, + paddingHorizontal: 12, paddingTop: 8, }, child: {}, diff --git a/src/view/com/util/PostContainer.tsx b/src/view/com/util/moderation/PostHider.tsx similarity index 87% rename from src/view/com/util/PostContainer.tsx rename to src/view/com/util/moderation/PostHider.tsx index 08807346ab..8d25fd38ba 100644 --- a/src/view/com/util/PostContainer.tsx +++ b/src/view/com/util/moderation/PostHider.tsx @@ -9,12 +9,12 @@ import { 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 {Link} from '../Link' +import {Text} from '../text/Text' import {getLabelValueGroup} from 'lib/labeling/helpers' import {addStyle} from 'lib/styles' -export function PostContainer({ +export function PostHider({ testID, href, isMuted, @@ -24,7 +24,7 @@ export function PostContainer({ }: React.PropsWithChildren<{ testID?: string href: string - isMuted: boolean + isMuted: boolean | undefined labels: ComAtprotoLabelDefs.Label[] | undefined style: StyleProp }>) { @@ -32,7 +32,14 @@ export function PostContainer({ const [override, setOverride] = React.useState(false) const bg = override ? pal.viewLight : pal.view - if (!isMuted && !labels?.length) { + const label = labels?.[0] // TODO use config to settle on most relevant item + const labelGroup = getLabelValueGroup(label?.val || '') + if (labelGroup.id === 'illegal') { + return <> + } + + if (!isMuted) { + // NOTE: any further label enforcement should occur in ContentContainer return ( {children} @@ -40,12 +47,6 @@ export function PostContainer({ ) } - const label = labels?.[0] // TODO use config to settle on most relevant item - const labelGroup = getLabelValueGroup(label?.val || '') - if (labelGroup.id === 'illegal') { - return <> - } - return ( <> @@ -54,13 +55,7 @@ export function PostContainer({ style={[styles.icon, pal.text]} /> - {isMuted ? ( - <>Post from an account you muted. - ) : label ? ( - <>Warning: {labelGroup.title} - ) : ( - '' - )} + Post from an account you muted.