@@ -48,7 +48,7 @@ export function PostThreadComposePrompt({
|
|||||||
accessibilityHint={_(msg`Opens composer`)}
|
accessibilityHint={_(msg`Opens composer`)}
|
||||||
style={[
|
style={[
|
||||||
gtMobile ? a.py_xs : {paddingTop: 8, paddingBottom: 11},
|
gtMobile ? a.py_xs : {paddingTop: 8, paddingBottom: 11},
|
||||||
gtMobile ? {paddingLeft: 6, paddingRight: 6} : a.px_sm,
|
a.px_sm,
|
||||||
a.border_t,
|
a.border_t,
|
||||||
t.atoms.border_contrast_low,
|
t.atoms.border_contrast_low,
|
||||||
t.atoms.bg,
|
t.atoms.bg,
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {StyleSheet, TouchableOpacity, View} from 'react-native'
|
|
||||||
import {AppBskyActorDefs} from '@atproto/api'
|
import {AppBskyActorDefs} from '@atproto/api'
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
|
||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
|
|
||||||
import {usePalette} from '#/lib/hooks/usePalette'
|
|
||||||
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
|
|
||||||
import {s} from '#/lib/styles'
|
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {Shadow, useProfileShadow} from '#/state/cache/profile-shadow'
|
import {Shadow, useProfileShadow} from '#/state/cache/profile-shadow'
|
||||||
import {
|
import {
|
||||||
@@ -16,8 +11,11 @@ import {
|
|||||||
useProfileQuery,
|
useProfileQuery,
|
||||||
} from '#/state/queries/profile'
|
} from '#/state/queries/profile'
|
||||||
import {useRequireAuth} from '#/state/session'
|
import {useRequireAuth} from '#/state/session'
|
||||||
import {Text} from '#/view/com/util/text/Text'
|
|
||||||
import * as Toast from '#/view/com/util/Toast'
|
import * as Toast from '#/view/com/util/Toast'
|
||||||
|
import {atoms as a, useBreakpoints} from '#/alf'
|
||||||
|
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||||
|
import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
|
||||||
|
import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus'
|
||||||
|
|
||||||
export function PostThreadFollowBtn({did}: {did: string}) {
|
export function PostThreadFollowBtn({did}: {did: string}) {
|
||||||
const {data: profile, isLoading} = useProfileQuery({did})
|
const {data: profile, isLoading} = useProfileQuery({did})
|
||||||
@@ -36,9 +34,7 @@ function PostThreadFollowBtnLoaded({
|
|||||||
}) {
|
}) {
|
||||||
const navigation = useNavigation()
|
const navigation = useNavigation()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const pal = usePalette('default')
|
const {gtMobile} = useBreakpoints()
|
||||||
const palInverted = usePalette('inverted')
|
|
||||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
|
||||||
const profile: Shadow<AppBskyActorDefs.ProfileViewBasic> =
|
const profile: Shadow<AppBskyActorDefs.ProfileViewBasic> =
|
||||||
useProfileShadow(profileUnshadowed)
|
useProfileShadow(profileUnshadowed)
|
||||||
const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue(
|
const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue(
|
||||||
@@ -113,51 +109,32 @@ function PostThreadFollowBtnLoaded({
|
|||||||
if (!showFollowBtn) return null
|
if (!showFollowBtn) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{width: isTabletOrDesktop ? 130 : 120}}>
|
<Button
|
||||||
<View style={styles.btnOuter}>
|
testID="followBtn"
|
||||||
<TouchableOpacity
|
label={_(msg`Follow ${profile.handle}`)}
|
||||||
testID="followBtn"
|
onPress={onPress}
|
||||||
onPress={onPress}
|
size="small"
|
||||||
style={[styles.btn, !isFollowing ? palInverted.view : pal.viewLight]}
|
variant="solid"
|
||||||
accessibilityRole="button"
|
color="secondary_inverted"
|
||||||
accessibilityLabel={_(msg`Follow ${profile.handle}`)}
|
style={[a.rounded_full]}>
|
||||||
accessibilityHint={_(
|
{gtMobile && (
|
||||||
msg`Shows posts from ${profile.handle} in your feed`,
|
<ButtonIcon
|
||||||
)}>
|
icon={isFollowing ? Check : Plus}
|
||||||
{isTabletOrDesktop && (
|
position="left"
|
||||||
<FontAwesomeIcon
|
size="sm"
|
||||||
icon={!isFollowing ? 'plus' : 'check'}
|
/>
|
||||||
style={[!isFollowing ? palInverted.text : pal.text, s.mr5]}
|
)}
|
||||||
/>
|
<ButtonText>
|
||||||
)}
|
{!isFollowing ? (
|
||||||
<Text
|
isFollowedBy ? (
|
||||||
type="button"
|
<Trans>Follow Back</Trans>
|
||||||
style={[!isFollowing ? palInverted.text : pal.text, s.bold]}
|
) : (
|
||||||
numberOfLines={1}>
|
<Trans>Follow</Trans>
|
||||||
{!isFollowing ? (
|
)
|
||||||
isFollowedBy ? (
|
) : (
|
||||||
<Trans>Follow Back</Trans>
|
<Trans>Following</Trans>
|
||||||
) : (
|
)}
|
||||||
<Trans>Follow</Trans>
|
</ButtonText>
|
||||||
)
|
</Button>
|
||||||
) : (
|
|
||||||
<Trans>Following</Trans>
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
btnOuter: {
|
|
||||||
marginLeft: 'auto',
|
|
||||||
},
|
|
||||||
btn: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
borderRadius: 50,
|
|
||||||
paddingVertical: 8,
|
|
||||||
paddingHorizontal: 14,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -14,14 +14,12 @@ import {useLingui} from '@lingui/react'
|
|||||||
|
|
||||||
import {MAX_POST_LINES} from '#/lib/constants'
|
import {MAX_POST_LINES} from '#/lib/constants'
|
||||||
import {usePalette} from '#/lib/hooks/usePalette'
|
import {usePalette} from '#/lib/hooks/usePalette'
|
||||||
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
|
|
||||||
import {makeProfileLink} from '#/lib/routes/links'
|
import {makeProfileLink} from '#/lib/routes/links'
|
||||||
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
||||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||||
import {countLines} from '#/lib/strings/helpers'
|
import {countLines} from '#/lib/strings/helpers'
|
||||||
import {niceDate} from '#/lib/strings/time'
|
import {niceDate} from '#/lib/strings/time'
|
||||||
import {s} from '#/lib/styles'
|
import {s} from '#/lib/styles'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {POST_TOMBSTONE, Shadow, usePostShadow} from '#/state/cache/post-shadow'
|
import {POST_TOMBSTONE, Shadow, usePostShadow} from '#/state/cache/post-shadow'
|
||||||
import {useLanguagePrefs} from '#/state/preferences'
|
import {useLanguagePrefs} from '#/state/preferences'
|
||||||
import {useOpenLink} from '#/state/preferences/in-app-browser'
|
import {useOpenLink} from '#/state/preferences/in-app-browser'
|
||||||
@@ -30,9 +28,10 @@ import {useSession} from '#/state/session'
|
|||||||
import {useComposerControls} from '#/state/shell/composer'
|
import {useComposerControls} from '#/state/shell/composer'
|
||||||
import {useMergedThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies'
|
import {useMergedThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies'
|
||||||
import {PostThreadFollowBtn} from '#/view/com/post-thread/PostThreadFollowBtn'
|
import {PostThreadFollowBtn} from '#/view/com/post-thread/PostThreadFollowBtn'
|
||||||
import {atoms as a} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {AppModerationCause} from '#/components/Pills'
|
import {AppModerationCause} from '#/components/Pills'
|
||||||
import {RichText} from '#/components/RichText'
|
import {RichText} from '#/components/RichText'
|
||||||
|
import {Text as NewText} from '#/components/Typography'
|
||||||
import {ContentHider} from '../../../components/moderation/ContentHider'
|
import {ContentHider} from '../../../components/moderation/ContentHider'
|
||||||
import {LabelsOnMyPost} from '../../../components/moderation/LabelsOnMe'
|
import {LabelsOnMyPost} from '../../../components/moderation/LabelsOnMe'
|
||||||
import {PostAlerts} from '../../../components/moderation/PostAlerts'
|
import {PostAlerts} from '../../../components/moderation/PostAlerts'
|
||||||
@@ -180,6 +179,7 @@ let PostThreadItemLoaded = ({
|
|||||||
hideTopBorder?: boolean
|
hideTopBorder?: boolean
|
||||||
threadgateRecord?: AppBskyFeedThreadgate.Record
|
threadgateRecord?: AppBskyFeedThreadgate.Record
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
|
const t = useTheme()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const {_, i18n} = useLingui()
|
const {_, i18n} = useLingui()
|
||||||
const langPrefs = useLanguagePrefs()
|
const langPrefs = useLanguagePrefs()
|
||||||
@@ -268,8 +268,14 @@ let PostThreadItemLoaded = ({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{rootUri !== post.uri && (
|
{rootUri !== post.uri && (
|
||||||
<View style={{paddingLeft: 16, flexDirection: 'row', height: 16}}>
|
<View
|
||||||
<View style={{width: 38}}>
|
style={[
|
||||||
|
a.pl_lg,
|
||||||
|
a.flex_row,
|
||||||
|
a.pb_xs,
|
||||||
|
{height: a.pt_lg.paddingTop},
|
||||||
|
]}>
|
||||||
|
<View style={{width: 42}}>
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.replyLine,
|
styles.replyLine,
|
||||||
@@ -286,88 +292,74 @@ let PostThreadItemLoaded = ({
|
|||||||
<View
|
<View
|
||||||
testID={`postThreadItem-by-${post.author.handle}`}
|
testID={`postThreadItem-by-${post.author.handle}`}
|
||||||
style={[
|
style={[
|
||||||
styles.outer,
|
a.px_lg,
|
||||||
styles.outerHighlighted,
|
t.atoms.border_contrast_low,
|
||||||
pal.border,
|
// root post styles
|
||||||
pal.view,
|
rootUri === post.uri && [a.pt_lg],
|
||||||
rootUri === post.uri && styles.outerHighlightedRoot,
|
]}>
|
||||||
hideTopBorder && styles.noTopBorder,
|
<View style={[a.flex_row, a.gap_md, a.pb_md]}>
|
||||||
]}
|
<PreviewableUserAvatar
|
||||||
accessible={false}>
|
size={42}
|
||||||
<View style={[styles.layout]}>
|
profile={post.author}
|
||||||
<View style={[styles.layoutAvi, {paddingBottom: 8}]}>
|
moderation={moderation.ui('avatar')}
|
||||||
<PreviewableUserAvatar
|
type={post.author.associated?.labeler ? 'labeler' : 'user'}
|
||||||
size={42}
|
/>
|
||||||
profile={post.author}
|
<View style={[a.flex_1]}>
|
||||||
moderation={moderation.ui('avatar')}
|
<Link style={s.flex1} href={authorHref} title={authorTitle}>
|
||||||
type={post.author.associated?.labeler ? 'labeler' : 'user'}
|
<NewText
|
||||||
/>
|
emoji
|
||||||
</View>
|
style={[a.text_lg, a.font_bold, a.leading_snug, a.self_start]}
|
||||||
<View style={styles.layoutContent}>
|
numberOfLines={1}>
|
||||||
<View
|
{sanitizeDisplayName(
|
||||||
style={[styles.meta, styles.metaExpandedLine1, {zIndex: 1}]}>
|
post.author.displayName ||
|
||||||
<Link style={s.flex1} href={authorHref} title={authorTitle}>
|
sanitizeHandle(post.author.handle),
|
||||||
<Text
|
moderation.ui('displayName'),
|
||||||
emoji
|
)}
|
||||||
type="xl-bold"
|
</NewText>
|
||||||
style={[pal.text, a.self_start]}
|
</Link>
|
||||||
numberOfLines={1}
|
<Link style={s.flex1} href={authorHref} title={authorTitle}>
|
||||||
lineHeight={1.2}>
|
<NewText
|
||||||
{sanitizeDisplayName(
|
emoji
|
||||||
post.author.displayName ||
|
style={[
|
||||||
sanitizeHandle(post.author.handle),
|
a.text_md,
|
||||||
moderation.ui('displayName'),
|
a.leading_snug,
|
||||||
)}
|
t.atoms.text_contrast_medium,
|
||||||
</Text>
|
]}
|
||||||
</Link>
|
numberOfLines={1}>
|
||||||
</View>
|
{sanitizeHandle(post.author.handle, '@')}
|
||||||
<View style={styles.meta}>
|
</NewText>
|
||||||
<Link style={s.flex1} href={authorHref} title={authorTitle}>
|
</Link>
|
||||||
<Text
|
|
||||||
emoji
|
|
||||||
type="md"
|
|
||||||
style={[pal.textLight]}
|
|
||||||
numberOfLines={1}>
|
|
||||||
{sanitizeHandle(post.author.handle, '@')}
|
|
||||||
</Text>
|
|
||||||
</Link>
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
{currentAccount?.did !== post.author.did && (
|
{currentAccount?.did !== post.author.did && (
|
||||||
<PostThreadFollowBtn did={post.author.did} />
|
<View>
|
||||||
|
<PostThreadFollowBtn did={post.author.did} />
|
||||||
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
<View style={[s.pl10, s.pr10, s.pb10]}>
|
<View style={[a.pb_sm]}>
|
||||||
<LabelsOnMyPost post={post} />
|
<LabelsOnMyPost post={post} style={[a.pb_sm]} />
|
||||||
<ContentHider
|
<ContentHider
|
||||||
modui={moderation.ui('contentView')}
|
modui={moderation.ui('contentView')}
|
||||||
ignoreMute
|
ignoreMute
|
||||||
style={styles.contentHider}
|
childContainerStyle={[a.pt_sm]}>
|
||||||
childContainerStyle={styles.contentHiderChild}>
|
|
||||||
<PostAlerts
|
<PostAlerts
|
||||||
modui={moderation.ui('contentView')}
|
modui={moderation.ui('contentView')}
|
||||||
size="lg"
|
size="lg"
|
||||||
includeMute
|
includeMute
|
||||||
style={[a.pt_2xs, a.pb_sm]}
|
style={[a.pb_sm]}
|
||||||
additionalCauses={additionalPostAlerts}
|
additionalCauses={additionalPostAlerts}
|
||||||
/>
|
/>
|
||||||
{richText?.text ? (
|
{richText?.text ? (
|
||||||
<View
|
<RichText
|
||||||
style={[
|
enableTags
|
||||||
styles.postTextContainer,
|
selectable
|
||||||
styles.postTextLargeContainer,
|
value={richText}
|
||||||
]}>
|
style={[a.flex_1, a.text_xl]}
|
||||||
<RichText
|
authorHandle={post.author.handle}
|
||||||
enableTags
|
/>
|
||||||
selectable
|
|
||||||
value={richText}
|
|
||||||
style={[a.flex_1, a.text_xl]}
|
|
||||||
authorHandle={post.author.handle}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
) : undefined}
|
) : undefined}
|
||||||
{post.embed && (
|
{post.embed && (
|
||||||
<View style={[a.pb_sm]}>
|
<View style={[a.py_xs]}>
|
||||||
<PostEmbeds
|
<PostEmbeds
|
||||||
embed={post.embed}
|
embed={post.embed}
|
||||||
moderation={moderation}
|
moderation={moderation}
|
||||||
@@ -386,68 +378,73 @@ let PostThreadItemLoaded = ({
|
|||||||
post.likeCount !== 0 ||
|
post.likeCount !== 0 ||
|
||||||
post.quoteCount !== 0 ? (
|
post.quoteCount !== 0 ? (
|
||||||
// Show this section unless we're *sure* it has no engagement.
|
// Show this section unless we're *sure* it has no engagement.
|
||||||
<View style={[styles.expandedInfo, pal.border]}>
|
<View
|
||||||
|
style={[
|
||||||
|
a.flex_row,
|
||||||
|
a.align_center,
|
||||||
|
a.gap_lg,
|
||||||
|
a.border_t,
|
||||||
|
a.border_b,
|
||||||
|
a.mt_md,
|
||||||
|
a.py_md,
|
||||||
|
t.atoms.border_contrast_low,
|
||||||
|
]}>
|
||||||
{post.repostCount != null && post.repostCount !== 0 ? (
|
{post.repostCount != null && post.repostCount !== 0 ? (
|
||||||
<Link
|
<Link href={repostsHref} title={repostsTitle}>
|
||||||
style={styles.expandedInfoItem}
|
<NewText
|
||||||
href={repostsHref}
|
|
||||||
title={repostsTitle}>
|
|
||||||
<Text
|
|
||||||
testID="repostCount-expanded"
|
testID="repostCount-expanded"
|
||||||
type="lg"
|
style={[a.text_md, t.atoms.text_contrast_medium]}>
|
||||||
style={pal.textLight}>
|
<NewText style={[a.text_md, a.font_bold, t.atoms.text]}>
|
||||||
<Text type="xl-bold" style={pal.text}>
|
|
||||||
{formatCount(i18n, post.repostCount)}
|
{formatCount(i18n, post.repostCount)}
|
||||||
</Text>{' '}
|
</NewText>{' '}
|
||||||
<Plural
|
<Plural
|
||||||
value={post.repostCount}
|
value={post.repostCount}
|
||||||
one="repost"
|
one="repost"
|
||||||
other="reposts"
|
other="reposts"
|
||||||
/>
|
/>
|
||||||
</Text>
|
</NewText>
|
||||||
</Link>
|
</Link>
|
||||||
) : null}
|
) : null}
|
||||||
{post.quoteCount != null &&
|
{post.quoteCount != null &&
|
||||||
post.quoteCount !== 0 &&
|
post.quoteCount !== 0 &&
|
||||||
!post.viewer?.embeddingDisabled ? (
|
!post.viewer?.embeddingDisabled ? (
|
||||||
<Link
|
<Link href={quotesHref} title={quotesTitle}>
|
||||||
style={styles.expandedInfoItem}
|
<NewText
|
||||||
href={quotesHref}
|
|
||||||
title={quotesTitle}>
|
|
||||||
<Text
|
|
||||||
testID="quoteCount-expanded"
|
testID="quoteCount-expanded"
|
||||||
type="lg"
|
style={[a.text_md, t.atoms.text_contrast_medium]}>
|
||||||
style={pal.textLight}>
|
<NewText style={[a.text_md, a.font_bold, t.atoms.text]}>
|
||||||
<Text type="xl-bold" style={pal.text}>
|
|
||||||
{formatCount(i18n, post.quoteCount)}
|
{formatCount(i18n, post.quoteCount)}
|
||||||
</Text>{' '}
|
</NewText>{' '}
|
||||||
<Plural
|
<Plural
|
||||||
value={post.quoteCount}
|
value={post.quoteCount}
|
||||||
one="quote"
|
one="quote"
|
||||||
other="quotes"
|
other="quotes"
|
||||||
/>
|
/>
|
||||||
</Text>
|
</NewText>
|
||||||
</Link>
|
</Link>
|
||||||
) : null}
|
) : null}
|
||||||
{post.likeCount != null && post.likeCount !== 0 ? (
|
{post.likeCount != null && post.likeCount !== 0 ? (
|
||||||
<Link
|
<Link href={likesHref} title={likesTitle}>
|
||||||
style={styles.expandedInfoItem}
|
<NewText
|
||||||
href={likesHref}
|
|
||||||
title={likesTitle}>
|
|
||||||
<Text
|
|
||||||
testID="likeCount-expanded"
|
testID="likeCount-expanded"
|
||||||
type="lg"
|
style={[a.text_md, t.atoms.text_contrast_medium]}>
|
||||||
style={pal.textLight}>
|
<NewText style={[a.text_md, a.font_bold, t.atoms.text]}>
|
||||||
<Text type="xl-bold" style={pal.text}>
|
|
||||||
{formatCount(i18n, post.likeCount)}
|
{formatCount(i18n, post.likeCount)}
|
||||||
</Text>{' '}
|
</NewText>{' '}
|
||||||
<Plural value={post.likeCount} one="like" other="likes" />
|
<Plural value={post.likeCount} one="like" other="likes" />
|
||||||
</Text>
|
</NewText>
|
||||||
</Link>
|
</Link>
|
||||||
) : null}
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
) : null}
|
) : null}
|
||||||
<View style={[s.pl10, s.pr10]}>
|
<View
|
||||||
|
style={[
|
||||||
|
a.pt_sm,
|
||||||
|
a.pb_2xs,
|
||||||
|
{
|
||||||
|
marginLeft: -5,
|
||||||
|
},
|
||||||
|
]}>
|
||||||
<PostCtrls
|
<PostCtrls
|
||||||
big
|
big
|
||||||
post={post}
|
post={post}
|
||||||
@@ -481,9 +478,8 @@ let PostThreadItemLoaded = ({
|
|||||||
testID={`postThreadItem-by-${post.author.handle}`}
|
testID={`postThreadItem-by-${post.author.handle}`}
|
||||||
href={postHref}
|
href={postHref}
|
||||||
disabled={overrideBlur}
|
disabled={overrideBlur}
|
||||||
style={[pal.view]}
|
|
||||||
modui={moderation.ui('contentList')}
|
modui={moderation.ui('contentList')}
|
||||||
iconSize={isThreadedChild ? 26 : 38}
|
iconSize={isThreadedChild ? 24 : 42}
|
||||||
iconStyles={
|
iconStyles={
|
||||||
isThreadedChild ? {marginRight: 4} : {marginLeft: 2, marginRight: 2}
|
isThreadedChild ? {marginRight: 4} : {marginLeft: 2, marginRight: 2}
|
||||||
}
|
}
|
||||||
@@ -496,7 +492,7 @@ let PostThreadItemLoaded = ({
|
|||||||
paddingLeft: 8,
|
paddingLeft: 8,
|
||||||
height: isThreadedChildAdjacentTop ? 8 : 16,
|
height: isThreadedChildAdjacentTop ? 8 : 16,
|
||||||
}}>
|
}}>
|
||||||
<View style={{width: 38}}>
|
<View style={{width: 42}}>
|
||||||
{!isThreadedChild && showParentReplyLine && (
|
{!isThreadedChild && showParentReplyLine && (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
@@ -514,7 +510,9 @@ let PostThreadItemLoaded = ({
|
|||||||
|
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.layout,
|
a.flex_row,
|
||||||
|
a.px_sm,
|
||||||
|
a.gap_md,
|
||||||
{
|
{
|
||||||
paddingBottom:
|
paddingBottom:
|
||||||
showChildReplyLine && !isThreadedChild
|
showChildReplyLine && !isThreadedChild
|
||||||
@@ -526,9 +524,9 @@ let PostThreadItemLoaded = ({
|
|||||||
]}>
|
]}>
|
||||||
{/* If we are in threaded mode, the avatar is rendered in PostMeta */}
|
{/* If we are in threaded mode, the avatar is rendered in PostMeta */}
|
||||||
{!isThreadedChild && (
|
{!isThreadedChild && (
|
||||||
<View style={styles.layoutAvi}>
|
<View>
|
||||||
<PreviewableUserAvatar
|
<PreviewableUserAvatar
|
||||||
size={38}
|
size={42}
|
||||||
profile={post.author}
|
profile={post.author}
|
||||||
moderation={moderation.ui('avatar')}
|
moderation={moderation.ui('avatar')}
|
||||||
type={post.author.associated?.labeler ? 'labeler' : 'user'}
|
type={post.author.associated?.labeler ? 'labeler' : 'user'}
|
||||||
@@ -549,12 +547,7 @@ let PostThreadItemLoaded = ({
|
|||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<View
|
<View style={[a.flex_1]}>
|
||||||
style={
|
|
||||||
isThreadedChild
|
|
||||||
? styles.layoutContentThreaded
|
|
||||||
: styles.layoutContent
|
|
||||||
}>
|
|
||||||
<PostMeta
|
<PostMeta
|
||||||
author={post.author}
|
author={post.author}
|
||||||
moderation={moderation}
|
moderation={moderation}
|
||||||
@@ -563,20 +556,16 @@ let PostThreadItemLoaded = ({
|
|||||||
showAvatar={isThreadedChild}
|
showAvatar={isThreadedChild}
|
||||||
avatarModeration={moderation.ui('avatar')}
|
avatarModeration={moderation.ui('avatar')}
|
||||||
avatarSize={24}
|
avatarSize={24}
|
||||||
style={
|
style={[a.pb_xs]}
|
||||||
isThreadedChild && {
|
|
||||||
paddingBottom: isWeb ? 5 : 4,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<LabelsOnMyPost post={post} />
|
<LabelsOnMyPost post={post} style={[a.pb_xs]} />
|
||||||
<PostAlerts
|
<PostAlerts
|
||||||
modui={moderation.ui('contentList')}
|
modui={moderation.ui('contentList')}
|
||||||
style={[a.pt_2xs, a.pb_2xs]}
|
style={[a.pb_2xs]}
|
||||||
additionalCauses={additionalPostAlerts}
|
additionalCauses={additionalPostAlerts}
|
||||||
/>
|
/>
|
||||||
{richText?.text ? (
|
{richText?.text ? (
|
||||||
<View style={styles.postTextContainer}>
|
<View style={[a.pb_2xs, a.pr_sm]}>
|
||||||
<RichText
|
<RichText
|
||||||
enableTags
|
enableTags
|
||||||
value={richText}
|
value={richText}
|
||||||
@@ -659,29 +648,31 @@ function PostOuterWrapper({
|
|||||||
hasPrecedingItem: boolean
|
hasPrecedingItem: boolean
|
||||||
hideTopBorder?: boolean
|
hideTopBorder?: boolean
|
||||||
}>) {
|
}>) {
|
||||||
const {isMobile} = useWebMediaQueries()
|
const t = useTheme()
|
||||||
const pal = usePalette('default')
|
|
||||||
if (treeView && depth > 0) {
|
if (treeView && depth > 0) {
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
pal.border,
|
a.flex_row,
|
||||||
|
a.px_sm,
|
||||||
|
t.atoms.border_contrast_low,
|
||||||
styles.cursor,
|
styles.cursor,
|
||||||
{
|
{
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
paddingHorizontal: isMobile ? 10 : 6,
|
borderTopWidth: depth === 1 ? a.border_t.borderTopWidth : 0,
|
||||||
borderTopWidth: depth === 1 ? StyleSheet.hairlineWidth : 0,
|
|
||||||
},
|
},
|
||||||
]}>
|
]}>
|
||||||
{Array.from(Array(depth - 1)).map((_, n: number) => (
|
{Array.from(Array(depth - 1)).map((_, n: number) => (
|
||||||
<View
|
<View
|
||||||
key={`${post.uri}-padding-${n}`}
|
key={`${post.uri}-padding-${n}`}
|
||||||
style={{
|
style={[
|
||||||
borderLeftWidth: 2,
|
a.ml_sm,
|
||||||
borderLeftColor: pal.colors.border,
|
t.atoms.border_contrast_low,
|
||||||
marginLeft: isMobile ? 6 : 12,
|
{
|
||||||
paddingLeft: isMobile ? 6 : 8,
|
borderLeftWidth: 2,
|
||||||
}}
|
paddingLeft: a.pl_sm.paddingLeft - 2, // minus border
|
||||||
|
},
|
||||||
|
]}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<View style={{flex: 1}}>{children}</View>
|
<View style={{flex: 1}}>{children}</View>
|
||||||
@@ -691,8 +682,9 @@ function PostOuterWrapper({
|
|||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.outer,
|
a.border_t,
|
||||||
pal.border,
|
a.px_sm,
|
||||||
|
t.atoms.border_contrast_low,
|
||||||
showParentReplyLine && hasPrecedingItem && styles.noTopBorder,
|
showParentReplyLine && hasPrecedingItem && styles.noTopBorder,
|
||||||
hideTopBorder && styles.noTopBorder,
|
hideTopBorder && styles.noTopBorder,
|
||||||
styles.cursor,
|
styles.cursor,
|
||||||
@@ -713,6 +705,7 @@ function ExpandedPostDetails({
|
|||||||
needsTranslation: boolean
|
needsTranslation: boolean
|
||||||
translatorUrl: string
|
translatorUrl: string
|
||||||
}) {
|
}) {
|
||||||
|
const t = useTheme()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const {_, i18n} = useLingui()
|
const {_, i18n} = useLingui()
|
||||||
const openLink = useOpenLink()
|
const openLink = useOpenLink()
|
||||||
@@ -723,31 +716,25 @@ function ExpandedPostDetails({
|
|||||||
}, [openLink, translatorUrl])
|
}, [openLink, translatorUrl])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View style={[a.flex_row, a.align_center, a.flex_wrap, a.gap_sm, a.pt_md]}>
|
||||||
style={[
|
<NewText style={[a.text_sm, t.atoms.text_contrast_medium]}>
|
||||||
a.flex_row,
|
|
||||||
a.align_center,
|
|
||||||
a.flex_wrap,
|
|
||||||
a.gap_xs,
|
|
||||||
s.mt2,
|
|
||||||
s.mb10,
|
|
||||||
]}>
|
|
||||||
<Text style={[a.text_sm, pal.textLight]}>
|
|
||||||
{niceDate(i18n, post.indexedAt)}
|
{niceDate(i18n, post.indexedAt)}
|
||||||
</Text>
|
</NewText>
|
||||||
{isRootPost && (
|
{isRootPost && (
|
||||||
<WhoCanReply post={post} isThreadAuthor={isThreadAuthor} />
|
<WhoCanReply post={post} isThreadAuthor={isThreadAuthor} />
|
||||||
)}
|
)}
|
||||||
{needsTranslation && (
|
{needsTranslation && (
|
||||||
<>
|
<>
|
||||||
<Text style={[a.text_sm, pal.textLight]}>·</Text>
|
<NewText style={[a.text_sm, t.atoms.text_contrast_medium]}>
|
||||||
|
·
|
||||||
|
</NewText>
|
||||||
|
|
||||||
<Text
|
<NewText
|
||||||
style={[a.text_sm, pal.link]}
|
style={[a.text_sm, pal.link]}
|
||||||
title={_(msg`Translate`)}
|
title={_(msg`Translate`)}
|
||||||
onPress={onTranslatePress}>
|
onPress={onTranslatePress}>
|
||||||
<Trans>Translate</Trans>
|
<Trans>Translate</Trans>
|
||||||
</Text>
|
</NewText>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
@@ -773,31 +760,9 @@ const styles = StyleSheet.create({
|
|||||||
borderTopWidth: StyleSheet.hairlineWidth,
|
borderTopWidth: StyleSheet.hairlineWidth,
|
||||||
paddingLeft: 8,
|
paddingLeft: 8,
|
||||||
},
|
},
|
||||||
outerHighlighted: {
|
|
||||||
borderTopWidth: 0,
|
|
||||||
paddingTop: 4,
|
|
||||||
paddingLeft: 8,
|
|
||||||
paddingRight: 8,
|
|
||||||
},
|
|
||||||
outerHighlightedRoot: {
|
|
||||||
borderTopWidth: StyleSheet.hairlineWidth,
|
|
||||||
paddingTop: 16,
|
|
||||||
},
|
|
||||||
noTopBorder: {
|
noTopBorder: {
|
||||||
borderTopWidth: 0,
|
borderTopWidth: 0,
|
||||||
},
|
},
|
||||||
layout: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
paddingHorizontal: 8,
|
|
||||||
},
|
|
||||||
layoutAvi: {},
|
|
||||||
layoutContent: {
|
|
||||||
flex: 1,
|
|
||||||
marginLeft: 10,
|
|
||||||
},
|
|
||||||
layoutContentThreaded: {
|
|
||||||
flex: 1,
|
|
||||||
},
|
|
||||||
meta: {
|
meta: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
paddingVertical: 2,
|
paddingVertical: 2,
|
||||||
@@ -805,42 +770,6 @@ const styles = StyleSheet.create({
|
|||||||
metaExpandedLine1: {
|
metaExpandedLine1: {
|
||||||
paddingVertical: 0,
|
paddingVertical: 0,
|
||||||
},
|
},
|
||||||
alert: {
|
|
||||||
marginBottom: 6,
|
|
||||||
},
|
|
||||||
postTextContainer: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
paddingBottom: 4,
|
|
||||||
paddingRight: 10,
|
|
||||||
overflow: 'hidden',
|
|
||||||
},
|
|
||||||
postTextLargeContainer: {
|
|
||||||
paddingHorizontal: 0,
|
|
||||||
paddingRight: 0,
|
|
||||||
paddingBottom: 10,
|
|
||||||
},
|
|
||||||
translateLink: {
|
|
||||||
marginBottom: 6,
|
|
||||||
},
|
|
||||||
contentHider: {
|
|
||||||
marginBottom: 6,
|
|
||||||
},
|
|
||||||
contentHiderChild: {
|
|
||||||
marginTop: 6,
|
|
||||||
},
|
|
||||||
expandedInfo: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
padding: 10,
|
|
||||||
borderTopWidth: StyleSheet.hairlineWidth,
|
|
||||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
|
||||||
marginTop: 5,
|
|
||||||
marginBottom: 10,
|
|
||||||
},
|
|
||||||
expandedInfoItem: {
|
|
||||||
marginRight: 10,
|
|
||||||
},
|
|
||||||
loadMore: {
|
loadMore: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
|||||||
Reference in New Issue
Block a user