Always show the header on post threads on native (#4254)
* always show header on native * ALF ALF ALF * rm offset for top border * wrap in a `CenteredView` * use `CenteredView`'s side borders * account for loading state on web * move `isTabletOrMobile` * hide top border on first post in list * show border if parents are loading * don't show top border for deleted or blocked posts * hide top border for hidden replies * Rm root post top border --------- Co-authored-by: Dan Abramov <dan.abramov@gmail.com>zio/stable
parent
9628070e52
commit
9edb487949
|
@ -1,5 +1,5 @@
|
|||
import React, {useEffect, useRef} from 'react'
|
||||
import {StyleSheet, useWindowDimensions, View} from 'react-native'
|
||||
import {useWindowDimensions, View} from 'react-native'
|
||||
import {runOnJS} from 'react-native-reanimated'
|
||||
import {AppBskyFeedDefs} from '@atproto/api'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
|
@ -22,15 +22,16 @@ import {
|
|||
import {usePreferencesQuery} from '#/state/queries/preferences'
|
||||
import {useSession} from '#/state/session'
|
||||
import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useSetTitle} from 'lib/hooks/useSetTitle'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {sanitizeDisplayName} from 'lib/strings/display-names'
|
||||
import {cleanError} from 'lib/strings/errors'
|
||||
import {CenteredView} from 'view/com/util/Views'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {ListFooter, ListMaybePlaceholder} from '#/components/Lists'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {ComposePrompt} from '../composer/Prompt'
|
||||
import {List, ListMethods} from '../util/List'
|
||||
import {Text} from '../util/text/Text'
|
||||
import {ViewHeader} from '../util/ViewHeader'
|
||||
import {PostThreadItem} from './PostThreadItem'
|
||||
import {PostThreadShowHiddenReplies} from './PostThreadShowHiddenReplies'
|
||||
|
@ -45,7 +46,6 @@ const MAINTAIN_VISIBLE_CONTENT_POSITION = {
|
|||
minIndexForVisible: 0,
|
||||
}
|
||||
|
||||
const TOP_COMPONENT = {_reactKey: '__top_component__'}
|
||||
const REPLY_PROMPT = {_reactKey: '__reply__'}
|
||||
const LOAD_MORE = {_reactKey: '__load_more__'}
|
||||
const SHOW_HIDDEN_REPLIES = {_reactKey: '__show_hidden_replies__'}
|
||||
|
@ -66,7 +66,6 @@ type YieldedItem =
|
|||
type RowItem =
|
||||
| YieldedItem
|
||||
// TODO: TS doesn't actually enforce it's one of these, it only enforces matching shape.
|
||||
| typeof TOP_COMPONENT
|
||||
| typeof REPLY_PROMPT
|
||||
| typeof LOAD_MORE
|
||||
|
||||
|
@ -91,7 +90,7 @@ export function PostThread({
|
|||
}) {
|
||||
const {hasSession} = useSession()
|
||||
const {_} = useLingui()
|
||||
const pal = usePalette('default')
|
||||
const t = useTheme()
|
||||
const {isMobile, isTabletOrMobile} = useWebMediaQueries()
|
||||
const initialNumToRender = useInitialNumToRender()
|
||||
const {height: windowHeight} = useWindowDimensions()
|
||||
|
@ -224,32 +223,21 @@ export function PostThread({
|
|||
const {parents, highlightedPost, replies} = skeleton
|
||||
let arr: RowItem[] = []
|
||||
if (highlightedPost.type === 'post') {
|
||||
const isRoot =
|
||||
!highlightedPost.parent && !highlightedPost.ctx.isParentLoading
|
||||
if (isRoot) {
|
||||
// No parents to load.
|
||||
arr.push(TOP_COMPONENT)
|
||||
} else {
|
||||
if (highlightedPost.ctx.isParentLoading || deferParents) {
|
||||
// We're loading parents of the highlighted post.
|
||||
// In this case, we don't render anything above the post.
|
||||
// If you add something here, you'll need to update both
|
||||
// maintainVisibleContentPosition and onContentSizeChange
|
||||
// to "hold onto" the correct row instead of the first one.
|
||||
} else {
|
||||
// Everything is loaded
|
||||
let startIndex = Math.max(0, parents.length - maxParents)
|
||||
if (startIndex === 0) {
|
||||
arr.push(TOP_COMPONENT)
|
||||
} else {
|
||||
// When progressively revealing parents, rendering a placeholder
|
||||
// here will cause scrolling jumps. Don't add it unless you test it.
|
||||
// QT'ing this thread is a great way to test all the scrolling hacks:
|
||||
// https://bsky.app/profile/www.mozzius.dev/post/3kjqhblh6qk2o
|
||||
}
|
||||
for (let i = startIndex; i < parents.length; i++) {
|
||||
arr.push(parents[i])
|
||||
}
|
||||
// We want to wait for parents to load before rendering.
|
||||
// If you add something here, you'll need to update both
|
||||
// maintainVisibleContentPosition and onContentSizeChange
|
||||
// to "hold onto" the correct row instead of the first one.
|
||||
|
||||
if (!highlightedPost.ctx.isParentLoading && !deferParents) {
|
||||
// When progressively revealing parents, rendering a placeholder
|
||||
// here will cause scrolling jumps. Don't add it unless you test it.
|
||||
// QT'ing this thread is a great way to test all the scrolling hacks:
|
||||
// https://bsky.app/profile/www.mozzius.dev/post/3kjqhblh6qk2o
|
||||
|
||||
// Everything is loaded
|
||||
let startIndex = Math.max(0, parents.length - maxParents)
|
||||
for (let i = startIndex; i < parents.length; i++) {
|
||||
arr.push(parents[i])
|
||||
}
|
||||
}
|
||||
arr.push(highlightedPost)
|
||||
|
@ -323,117 +311,100 @@ export function PostThread({
|
|||
setMaxReplies(prev => prev + 50)
|
||||
}, [isFetching, maxReplies, posts.length])
|
||||
|
||||
const renderItem = React.useCallback(
|
||||
({item, index}: {item: RowItem; index: number}) => {
|
||||
if (item === TOP_COMPONENT) {
|
||||
return isTabletOrMobile ? (
|
||||
<ViewHeader
|
||||
title={_(msg({message: `Post`, context: 'description'}))}
|
||||
/>
|
||||
) : null
|
||||
} else if (item === REPLY_PROMPT && hasSession) {
|
||||
return (
|
||||
<View>
|
||||
{!isMobile && <ComposePrompt onPressCompose={onPressReply} />}
|
||||
</View>
|
||||
)
|
||||
} else if (item === SHOW_HIDDEN_REPLIES) {
|
||||
return (
|
||||
<PostThreadShowHiddenReplies
|
||||
type="hidden"
|
||||
onPress={() =>
|
||||
setHiddenRepliesState(HiddenRepliesState.ShowAndOverridePostHider)
|
||||
const hasParents =
|
||||
skeleton?.highlightedPost?.type === 'post' &&
|
||||
(skeleton.highlightedPost.ctx.isParentLoading ||
|
||||
Boolean(skeleton?.parents && skeleton.parents.length > 0))
|
||||
const showHeader =
|
||||
isNative || (isTabletOrMobile && (!hasParents || !isFetching))
|
||||
|
||||
const renderItem = ({item, index}: {item: RowItem; index: number}) => {
|
||||
if (item === REPLY_PROMPT && hasSession) {
|
||||
return (
|
||||
<View>
|
||||
{!isMobile && <ComposePrompt onPressCompose={onPressReply} />}
|
||||
</View>
|
||||
)
|
||||
} else if (item === SHOW_HIDDEN_REPLIES || item === SHOW_MUTED_REPLIES) {
|
||||
return (
|
||||
<PostThreadShowHiddenReplies
|
||||
type={item === SHOW_HIDDEN_REPLIES ? 'hidden' : 'muted'}
|
||||
onPress={() =>
|
||||
setHiddenRepliesState(HiddenRepliesState.ShowAndOverridePostHider)
|
||||
}
|
||||
hideTopBorder={index === 0}
|
||||
/>
|
||||
)
|
||||
} else if (isThreadNotFound(item)) {
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
a.p_lg,
|
||||
index !== 0 && a.border_t,
|
||||
t.atoms.border_contrast_low,
|
||||
t.atoms.bg_contrast_25,
|
||||
]}>
|
||||
<Text style={[a.font_bold, a.text_md, t.atoms.text_contrast_medium]}>
|
||||
<Trans>Deleted post.</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
)
|
||||
} else if (isThreadBlocked(item)) {
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
a.p_lg,
|
||||
index !== 0 && a.border_t,
|
||||
t.atoms.border_contrast_low,
|
||||
t.atoms.bg_contrast_25,
|
||||
]}>
|
||||
<Text style={[a.font_bold, a.text_md, t.atoms.text_contrast_medium]}>
|
||||
<Trans>Blocked post.</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
)
|
||||
} else if (isThreadPost(item)) {
|
||||
const prev = isThreadPost(posts[index - 1])
|
||||
? (posts[index - 1] as ThreadPost)
|
||||
: undefined
|
||||
const next = isThreadPost(posts[index + 1])
|
||||
? (posts[index + 1] as ThreadPost)
|
||||
: undefined
|
||||
const showChildReplyLine = (next?.ctx.depth || 0) > item.ctx.depth
|
||||
const showParentReplyLine =
|
||||
(item.ctx.depth < 0 && !!item.parent) || item.ctx.depth > 1
|
||||
const hasUnrevealedParents =
|
||||
index === 0 && skeleton?.parents && maxParents < skeleton.parents.length
|
||||
return (
|
||||
<View
|
||||
ref={item.ctx.isHighlightedPost ? highlightedPostRef : undefined}
|
||||
onLayout={deferParents ? () => setDeferParents(false) : undefined}>
|
||||
<PostThreadItem
|
||||
post={item.post}
|
||||
record={item.record}
|
||||
moderation={threadModerationCache.get(item)}
|
||||
treeView={treeView}
|
||||
depth={item.ctx.depth}
|
||||
prevPost={prev}
|
||||
nextPost={next}
|
||||
isHighlightedPost={item.ctx.isHighlightedPost}
|
||||
hasMore={item.ctx.hasMore}
|
||||
showChildReplyLine={showChildReplyLine}
|
||||
showParentReplyLine={showParentReplyLine}
|
||||
hasPrecedingItem={showParentReplyLine || !!hasUnrevealedParents}
|
||||
overrideBlur={
|
||||
hiddenRepliesState ===
|
||||
HiddenRepliesState.ShowAndOverridePostHider &&
|
||||
item.ctx.depth > 0
|
||||
}
|
||||
onPostReply={refetch}
|
||||
hideTopBorder={index === 0 && !item.ctx.isParentLoading}
|
||||
/>
|
||||
)
|
||||
} else if (item === SHOW_MUTED_REPLIES) {
|
||||
return (
|
||||
<PostThreadShowHiddenReplies
|
||||
type="muted"
|
||||
onPress={() =>
|
||||
setHiddenRepliesState(HiddenRepliesState.ShowAndOverridePostHider)
|
||||
}
|
||||
/>
|
||||
)
|
||||
} else if (isThreadNotFound(item)) {
|
||||
return (
|
||||
<View style={[pal.border, pal.viewLight, styles.itemContainer]}>
|
||||
<Text type="lg-bold" style={pal.textLight}>
|
||||
<Trans>Deleted post.</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
)
|
||||
} else if (isThreadBlocked(item)) {
|
||||
return (
|
||||
<View style={[pal.border, pal.viewLight, styles.itemContainer]}>
|
||||
<Text type="lg-bold" style={pal.textLight}>
|
||||
<Trans>Blocked post.</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
)
|
||||
} else if (isThreadPost(item)) {
|
||||
const prev = isThreadPost(posts[index - 1])
|
||||
? (posts[index - 1] as ThreadPost)
|
||||
: undefined
|
||||
const next = isThreadPost(posts[index + 1])
|
||||
? (posts[index + 1] as ThreadPost)
|
||||
: undefined
|
||||
const showChildReplyLine = (next?.ctx.depth || 0) > item.ctx.depth
|
||||
const showParentReplyLine =
|
||||
(item.ctx.depth < 0 && !!item.parent) || item.ctx.depth > 1
|
||||
const hasUnrevealedParents =
|
||||
index === 0 &&
|
||||
skeleton?.parents &&
|
||||
maxParents < skeleton.parents.length
|
||||
return (
|
||||
<View
|
||||
ref={item.ctx.isHighlightedPost ? highlightedPostRef : undefined}
|
||||
onLayout={deferParents ? () => setDeferParents(false) : undefined}>
|
||||
<PostThreadItem
|
||||
post={item.post}
|
||||
record={item.record}
|
||||
moderation={threadModerationCache.get(item)}
|
||||
treeView={treeView}
|
||||
depth={item.ctx.depth}
|
||||
prevPost={prev}
|
||||
nextPost={next}
|
||||
isHighlightedPost={item.ctx.isHighlightedPost}
|
||||
hasMore={item.ctx.hasMore}
|
||||
showChildReplyLine={showChildReplyLine}
|
||||
showParentReplyLine={showParentReplyLine}
|
||||
hasPrecedingItem={showParentReplyLine || !!hasUnrevealedParents}
|
||||
overrideBlur={
|
||||
hiddenRepliesState ===
|
||||
HiddenRepliesState.ShowAndOverridePostHider &&
|
||||
item.ctx.depth > 0
|
||||
}
|
||||
onPostReply={refetch}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
return null
|
||||
},
|
||||
[
|
||||
hasSession,
|
||||
isTabletOrMobile,
|
||||
_,
|
||||
isMobile,
|
||||
onPressReply,
|
||||
pal.border,
|
||||
pal.viewLight,
|
||||
pal.textLight,
|
||||
posts,
|
||||
skeleton?.parents,
|
||||
maxParents,
|
||||
deferParents,
|
||||
treeView,
|
||||
refetch,
|
||||
threadModerationCache,
|
||||
hiddenRepliesState,
|
||||
setHiddenRepliesState,
|
||||
],
|
||||
)
|
||||
</View>
|
||||
)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
if (!thread || !preferences || error) {
|
||||
return (
|
||||
|
@ -449,39 +420,49 @@ export function PostThread({
|
|||
}
|
||||
|
||||
return (
|
||||
<ScrollProvider onMomentumEnd={onMomentumEnd}>
|
||||
<List
|
||||
ref={ref}
|
||||
data={posts}
|
||||
renderItem={renderItem}
|
||||
keyExtractor={keyExtractor}
|
||||
onContentSizeChange={isNative ? undefined : onContentSizeChangeWeb}
|
||||
onStartReached={onStartReached}
|
||||
onEndReached={onEndReached}
|
||||
onEndReachedThreshold={2}
|
||||
onScrollToTop={onScrollToTop}
|
||||
maintainVisibleContentPosition={
|
||||
isNative ? MAINTAIN_VISIBLE_CONTENT_POSITION : undefined
|
||||
}
|
||||
// @ts-ignore our .web version only -prf
|
||||
desktopFixedHeight
|
||||
removeClippedSubviews={isAndroid ? false : undefined}
|
||||
ListFooterComponent={
|
||||
<ListFooter
|
||||
// Using `isFetching` over `isFetchingNextPage` is done on purpose here so we get the loader on
|
||||
// initial render
|
||||
isFetchingNextPage={isFetching}
|
||||
error={cleanError(threadError)}
|
||||
onRetry={refetch}
|
||||
// 300 is based on the minimum height of a post. This is enough extra height for the `maintainVisPos` to
|
||||
// work without causing weird jumps on web or glitches on native
|
||||
height={windowHeight - 200}
|
||||
/>
|
||||
}
|
||||
initialNumToRender={initialNumToRender}
|
||||
windowSize={11}
|
||||
/>
|
||||
</ScrollProvider>
|
||||
<CenteredView style={[a.flex_1]} sideBorders={true}>
|
||||
{showHeader && (
|
||||
<ViewHeader
|
||||
title={_(msg({message: `Post`, context: 'description'}))}
|
||||
showBorder
|
||||
/>
|
||||
)}
|
||||
|
||||
<ScrollProvider onMomentumEnd={onMomentumEnd}>
|
||||
<List
|
||||
ref={ref}
|
||||
data={posts}
|
||||
renderItem={renderItem}
|
||||
keyExtractor={keyExtractor}
|
||||
onContentSizeChange={isNative ? undefined : onContentSizeChangeWeb}
|
||||
onStartReached={onStartReached}
|
||||
onEndReached={onEndReached}
|
||||
onEndReachedThreshold={2}
|
||||
onScrollToTop={onScrollToTop}
|
||||
maintainVisibleContentPosition={
|
||||
isNative ? MAINTAIN_VISIBLE_CONTENT_POSITION : undefined
|
||||
}
|
||||
// @ts-ignore our .web version only -prf
|
||||
desktopFixedHeight
|
||||
removeClippedSubviews={isAndroid ? false : undefined}
|
||||
ListFooterComponent={
|
||||
<ListFooter
|
||||
// Using `isFetching` over `isFetchingNextPage` is done on purpose here so we get the loader on
|
||||
// initial render
|
||||
isFetchingNextPage={isFetching}
|
||||
error={cleanError(threadError)}
|
||||
onRetry={refetch}
|
||||
// 300 is based on the minimum height of a post. This is enough extra height for the `maintainVisPos` to
|
||||
// work without causing weird jumps on web or glitches on native
|
||||
height={windowHeight - 200}
|
||||
/>
|
||||
}
|
||||
initialNumToRender={initialNumToRender}
|
||||
windowSize={11}
|
||||
sideBorders={false}
|
||||
/>
|
||||
</ScrollProvider>
|
||||
</CenteredView>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -630,11 +611,3 @@ function hasBranchingReplies(node?: ThreadNode) {
|
|||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
itemContainer: {
|
||||
borderTopWidth: 1,
|
||||
paddingHorizontal: 18,
|
||||
paddingVertical: 18,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -65,6 +65,7 @@ export function PostThreadItem({
|
|||
hasPrecedingItem,
|
||||
overrideBlur,
|
||||
onPostReply,
|
||||
hideTopBorder,
|
||||
}: {
|
||||
post: AppBskyFeedDefs.PostView
|
||||
record: AppBskyFeedPost.Record
|
||||
|
@ -80,6 +81,7 @@ export function PostThreadItem({
|
|||
hasPrecedingItem: boolean
|
||||
overrideBlur: boolean
|
||||
onPostReply: () => void
|
||||
hideTopBorder?: boolean
|
||||
}) {
|
||||
const postShadowed = usePostShadow(post)
|
||||
const richText = useMemo(
|
||||
|
@ -91,7 +93,7 @@ export function PostThreadItem({
|
|||
[record],
|
||||
)
|
||||
if (postShadowed === POST_TOMBSTONE) {
|
||||
return <PostThreadItemDeleted />
|
||||
return <PostThreadItemDeleted hideTopBorder={hideTopBorder} />
|
||||
}
|
||||
if (richText && moderation) {
|
||||
return (
|
||||
|
@ -113,16 +115,25 @@ export function PostThreadItem({
|
|||
hasPrecedingItem={hasPrecedingItem}
|
||||
overrideBlur={overrideBlur}
|
||||
onPostReply={onPostReply}
|
||||
hideTopBorder={hideTopBorder}
|
||||
/>
|
||||
)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function PostThreadItemDeleted() {
|
||||
function PostThreadItemDeleted({hideTopBorder}: {hideTopBorder?: boolean}) {
|
||||
const pal = usePalette('default')
|
||||
return (
|
||||
<View style={[styles.outer, pal.border, pal.view, s.p20, s.flexRow]}>
|
||||
<View
|
||||
style={[
|
||||
styles.outer,
|
||||
pal.border,
|
||||
pal.view,
|
||||
s.p20,
|
||||
s.flexRow,
|
||||
hideTopBorder && styles.noTopBorder,
|
||||
]}>
|
||||
<FontAwesomeIcon icon={['far', 'trash-can']} color={pal.colors.icon} />
|
||||
<Text style={[pal.textLight, s.ml10]}>
|
||||
<Trans>This post has been deleted.</Trans>
|
||||
|
@ -147,6 +158,7 @@ let PostThreadItemLoaded = ({
|
|||
hasPrecedingItem,
|
||||
overrideBlur,
|
||||
onPostReply,
|
||||
hideTopBorder,
|
||||
}: {
|
||||
post: Shadow<AppBskyFeedDefs.PostView>
|
||||
record: AppBskyFeedPost.Record
|
||||
|
@ -163,6 +175,7 @@ let PostThreadItemLoaded = ({
|
|||
hasPrecedingItem: boolean
|
||||
overrideBlur: boolean
|
||||
onPostReply: () => void
|
||||
hideTopBorder?: boolean
|
||||
}): React.ReactNode => {
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
|
@ -237,7 +250,7 @@ let PostThreadItemLoaded = ({
|
|||
styles.replyLine,
|
||||
{
|
||||
flexGrow: 1,
|
||||
backgroundColor: pal.colors.border,
|
||||
backgroundColor: pal.colors.replyLine,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
@ -247,7 +260,14 @@ let PostThreadItemLoaded = ({
|
|||
|
||||
<View
|
||||
testID={`postThreadItem-by-${post.author.handle}`}
|
||||
style={[styles.outer, styles.outerHighlighted, pal.border, pal.view]}
|
||||
style={[
|
||||
styles.outer,
|
||||
styles.outerHighlighted,
|
||||
pal.border,
|
||||
pal.view,
|
||||
rootUri === post.uri && styles.outerHighlightedRoot,
|
||||
hideTopBorder && styles.noTopBorder,
|
||||
]}
|
||||
accessible={false}>
|
||||
<View style={[styles.layout]}>
|
||||
<View style={[styles.layoutAvi, {paddingBottom: 8}]}>
|
||||
|
@ -395,7 +415,8 @@ let PostThreadItemLoaded = ({
|
|||
depth={depth}
|
||||
showParentReplyLine={!!showParentReplyLine}
|
||||
treeView={treeView}
|
||||
hasPrecedingItem={hasPrecedingItem}>
|
||||
hasPrecedingItem={hasPrecedingItem}
|
||||
hideTopBorder={hideTopBorder}>
|
||||
<PostHider
|
||||
testID={`postThreadItem-by-${post.author.handle}`}
|
||||
href={postHref}
|
||||
|
@ -574,6 +595,7 @@ function PostOuterWrapper({
|
|||
depth,
|
||||
showParentReplyLine,
|
||||
hasPrecedingItem,
|
||||
hideTopBorder,
|
||||
children,
|
||||
}: React.PropsWithChildren<{
|
||||
post: AppBskyFeedDefs.PostView
|
||||
|
@ -581,6 +603,7 @@ function PostOuterWrapper({
|
|||
depth: number
|
||||
showParentReplyLine: boolean
|
||||
hasPrecedingItem: boolean
|
||||
hideTopBorder?: boolean
|
||||
}>) {
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const pal = usePalette('default')
|
||||
|
@ -617,6 +640,7 @@ function PostOuterWrapper({
|
|||
styles.outer,
|
||||
pal.border,
|
||||
showParentReplyLine && hasPrecedingItem && styles.noTopBorder,
|
||||
hideTopBorder && styles.noTopBorder,
|
||||
styles.cursor,
|
||||
]}>
|
||||
{children}
|
||||
|
@ -677,10 +701,15 @@ const styles = StyleSheet.create({
|
|||
paddingLeft: 8,
|
||||
},
|
||||
outerHighlighted: {
|
||||
paddingTop: 16,
|
||||
borderTopWidth: 0,
|
||||
paddingTop: 4,
|
||||
paddingLeft: 8,
|
||||
paddingRight: 8,
|
||||
},
|
||||
outerHighlightedRoot: {
|
||||
borderTopWidth: 1,
|
||||
paddingTop: 16,
|
||||
},
|
||||
noTopBorder: {
|
||||
borderTopWidth: 0,
|
||||
},
|
||||
|
|
|
@ -11,9 +11,11 @@ import {Text} from '#/components/Typography'
|
|||
export function PostThreadShowHiddenReplies({
|
||||
type,
|
||||
onPress,
|
||||
hideTopBorder,
|
||||
}: {
|
||||
type: 'hidden' | 'muted'
|
||||
onPress: () => void
|
||||
hideTopBorder?: boolean
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const t = useTheme()
|
||||
|
@ -31,7 +33,7 @@ export function PostThreadShowHiddenReplies({
|
|||
a.gap_sm,
|
||||
a.py_lg,
|
||||
a.px_xl,
|
||||
a.border_t,
|
||||
!hideTopBorder && a.border_t,
|
||||
t.atoms.border_contrast_low,
|
||||
hovered || pressed ? t.atoms.bg_contrast_25 : t.atoms.bg,
|
||||
]}>
|
||||
|
|
Loading…
Reference in New Issue