Remove post from feed after pressing show less (#8333)

* remove post from feed after pressing show less

* fix text overflow on android

* move state up so it won't get recycled away

* make type optional
This commit is contained in:
Samuel Newman
2025-05-06 17:34:50 +03:00
committed by GitHub
parent 04dc6dc9ca
commit 25f8506c41
6 changed files with 183 additions and 60 deletions
+60 -10
View File
@@ -1,15 +1,20 @@
import React, {memo} from 'react' import React, {memo, useCallback} from 'react'
import { import {
ActivityIndicator, ActivityIndicator,
AppState, AppState,
Dimensions, Dimensions,
LayoutAnimation,
type ListRenderItemInfo, type ListRenderItemInfo,
type StyleProp, type StyleProp,
StyleSheet, StyleSheet,
View, View,
type ViewStyle, type ViewStyle,
} from 'react-native' } from 'react-native'
import {type AppBskyActorDefs, AppBskyEmbedVideo} from '@atproto/api' import {
type AppBskyActorDefs,
AppBskyEmbedVideo,
type AppBskyFeedDefs,
} from '@atproto/api'
import {msg} from '@lingui/macro' import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
@@ -51,6 +56,7 @@ import {DiscoverFallbackHeader} from './DiscoverFallbackHeader'
import {FeedShutdownMsg} from './FeedShutdownMsg' import {FeedShutdownMsg} from './FeedShutdownMsg'
import {PostFeedErrorMessage} from './PostFeedErrorMessage' import {PostFeedErrorMessage} from './PostFeedErrorMessage'
import {PostFeedItem} from './PostFeedItem' import {PostFeedItem} from './PostFeedItem'
import {ShowLessFollowup} from './ShowLessFollowup'
import {ViewFullThread} from './ViewFullThread' import {ViewFullThread} from './ViewFullThread'
type FeedRow = type FeedRow =
@@ -117,6 +123,10 @@ type FeedRow =
type: 'interstitialTrendingVideos' type: 'interstitialTrendingVideos'
key: string key: string
} }
| {
type: 'showLessFollowup'
key: string
}
export function getItemsForFeedback(feedRow: FeedRow): export function getItemsForFeedback(feedRow: FeedRow):
| { | {
@@ -200,6 +210,20 @@ let PostFeed = ({
const {rightNavVisible} = useLayoutBreakpoints() const {rightNavVisible} = useLayoutBreakpoints()
const areVideoFeedsEnabled = isNative const areVideoFeedsEnabled = isNative
const [hasPressedShowLessUris, setHasPressedShowLessUris] = React.useState(
() => new Set<string>(),
)
const onPressShowLess = useCallback(
(interaction: AppBskyFeedDefs.Interaction) => {
if (interaction.item) {
const uri = interaction.item
setHasPressedShowLessUris(prev => new Set([...prev, uri]))
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
}
},
[],
)
const feedCacheKey = feedParams?.feedCacheKey const feedCacheKey = feedParams?.feedCacheKey
const opts = React.useMemo( const opts = React.useMemo(
() => ({enabled, ignoreFilterFor}), () => ({enabled, ignoreFilterFor}),
@@ -321,6 +345,19 @@ let PostFeed = ({
const {trendingDisabled, trendingVideoDisabled} = useTrendingSettings() const {trendingDisabled, trendingVideoDisabled} = useTrendingSettings()
const feedItems: FeedRow[] = React.useMemo(() => { const feedItems: FeedRow[] = React.useMemo(() => {
// wraps a slice item, and replaces it with a showLessFollowup item
// if the user has pressed show less on it
const sliceItem = (row: Extract<FeedRow, {type: 'sliceItem'}>) => {
if (hasPressedShowLessUris.has(row.slice.items[row.indexInSlice]?.uri)) {
return {
type: 'showLessFollowup',
key: row.key,
} as const
} else {
return row
}
}
let feedKind: 'following' | 'discover' | 'profile' | 'thevids' | undefined let feedKind: 'following' | 'discover' | 'profile' | 'thevids' | undefined
if (feedType === 'following') { if (feedType === 'following') {
feedKind = 'following' feedKind = 'following'
@@ -450,19 +487,22 @@ let PostFeed = ({
} else if (slice.isIncompleteThread && slice.items.length >= 3) { } else if (slice.isIncompleteThread && slice.items.length >= 3) {
const beforeLast = slice.items.length - 2 const beforeLast = slice.items.length - 2
const last = slice.items.length - 1 const last = slice.items.length - 1
arr.push({ arr.push(
sliceItem({
type: 'sliceItem', type: 'sliceItem',
key: slice.items[0]._reactKey, key: slice.items[0]._reactKey,
slice: slice, slice: slice,
indexInSlice: 0, indexInSlice: 0,
showReplyTo: false, showReplyTo: false,
}) }),
)
arr.push({ arr.push({
type: 'sliceViewFullThread', type: 'sliceViewFullThread',
key: slice._reactKey + '-viewFullThread', key: slice._reactKey + '-viewFullThread',
uri: slice.items[0].uri, uri: slice.items[0].uri,
}) })
arr.push({ arr.push(
sliceItem({
type: 'sliceItem', type: 'sliceItem',
key: slice.items[beforeLast]._reactKey, key: slice.items[beforeLast]._reactKey,
slice: slice, slice: slice,
@@ -470,23 +510,28 @@ let PostFeed = ({
showReplyTo: showReplyTo:
slice.items[beforeLast].parentAuthor?.did !== slice.items[beforeLast].parentAuthor?.did !==
slice.items[beforeLast].post.author.did, slice.items[beforeLast].post.author.did,
}) }),
arr.push({ )
arr.push(
sliceItem({
type: 'sliceItem', type: 'sliceItem',
key: slice.items[last]._reactKey, key: slice.items[last]._reactKey,
slice: slice, slice: slice,
indexInSlice: last, indexInSlice: last,
showReplyTo: false, showReplyTo: false,
}) }),
)
} else { } else {
for (let i = 0; i < slice.items.length; i++) { for (let i = 0; i < slice.items.length; i++) {
arr.push({ arr.push(
sliceItem({
type: 'sliceItem', type: 'sliceItem',
key: slice.items[i]._reactKey, key: slice.items[i]._reactKey,
slice: slice, slice: slice,
indexInSlice: i, indexInSlice: i,
showReplyTo: i === 0, showReplyTo: i === 0,
}) }),
)
} }
} }
} }
@@ -531,6 +576,7 @@ let PostFeed = ({
gtMobile, gtMobile,
isVideoFeed, isVideoFeed,
areVideoFeedsEnabled, areVideoFeedsEnabled,
hasPressedShowLessUris,
]) ])
// events // events
@@ -650,6 +696,7 @@ let PostFeed = ({
isParentNotFound={item.isParentNotFound} isParentNotFound={item.isParentNotFound}
hideTopBorder={rowIndex === 0 && indexInSlice === 0} hideTopBorder={rowIndex === 0 && indexInSlice === 0}
rootPost={slice.items[0].post} rootPost={slice.items[0].post}
onShowLess={onPressShowLess}
/> />
) )
} else if (row.type === 'sliceViewFullThread') { } else if (row.type === 'sliceViewFullThread') {
@@ -684,6 +731,8 @@ let PostFeed = ({
sourceContext={sourceContext} sourceContext={sourceContext}
/> />
) )
} else if (row.type === 'showLessFollowup') {
return <ShowLessFollowup />
} else { } else {
return null return null
} }
@@ -700,6 +749,7 @@ let PostFeed = ({
feedUriOrActorDid, feedUriOrActorDid,
feedTab, feedTab,
feedCacheKey, feedCacheKey,
onPressShowLess,
], ],
) )
+26 -15
View File
@@ -1,23 +1,23 @@
import React, {memo, useMemo, useState} from 'react' import {memo, useCallback, useMemo, useState} from 'react'
import {StyleSheet, View} from 'react-native' import {StyleSheet, View} from 'react-native'
import { import {
AppBskyActorDefs, type AppBskyActorDefs,
AppBskyFeedDefs, AppBskyFeedDefs,
AppBskyFeedPost, AppBskyFeedPost,
AppBskyFeedThreadgate, AppBskyFeedThreadgate,
AtUri, AtUri,
ModerationDecision, type ModerationDecision,
RichText as RichTextAPI, RichText as RichTextAPI,
} from '@atproto/api' } from '@atproto/api'
import { import {
FontAwesomeIcon, FontAwesomeIcon,
FontAwesomeIconStyle, type FontAwesomeIconStyle,
} from '@fortawesome/react-native-fontawesome' } 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 {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
import {isReasonFeedSource, ReasonFeedSource} from '#/lib/api/feed/types' import {isReasonFeedSource, type ReasonFeedSource} from '#/lib/api/feed/types'
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 {makeProfileLink} from '#/lib/routes/links' import {makeProfileLink} from '#/lib/routes/links'
@@ -25,7 +25,11 @@ 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 {s} from '#/lib/styles' import {s} from '#/lib/styles'
import {POST_TOMBSTONE, Shadow, usePostShadow} from '#/state/cache/post-shadow' import {
POST_TOMBSTONE,
type Shadow,
usePostShadow,
} from '#/state/cache/post-shadow'
import {useFeedFeedbackContext} from '#/state/feed-feedback' import {useFeedFeedbackContext} from '#/state/feed-feedback'
import {precacheProfile} from '#/state/queries/profile' import {precacheProfile} from '#/state/queries/profile'
import {useSession} from '#/state/session' import {useSession} from '#/state/session'
@@ -43,7 +47,7 @@ import {Repost_Stroke2_Corner2_Rounded as RepostIcon} from '#/components/icons/R
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'
import {AppModerationCause} from '#/components/Pills' import {type AppModerationCause} from '#/components/Pills'
import {ProfileHoverCard} from '#/components/ProfileHoverCard' import {ProfileHoverCard} from '#/components/ProfileHoverCard'
import {RichText} from '#/components/RichText' import {RichText} from '#/components/RichText'
import {SubtleWebHover} from '#/components/SubtleWebHover' import {SubtleWebHover} from '#/components/SubtleWebHover'
@@ -86,9 +90,11 @@ export function PostFeedItem({
isParentBlocked, isParentBlocked,
isParentNotFound, isParentNotFound,
rootPost, rootPost,
onShowLess,
}: FeedItemProps & { }: FeedItemProps & {
post: AppBskyFeedDefs.PostView post: AppBskyFeedDefs.PostView
rootPost: AppBskyFeedDefs.PostView rootPost: AppBskyFeedDefs.PostView
onShowLess?: (interaction: AppBskyFeedDefs.Interaction) => void
}): React.ReactNode { }): React.ReactNode {
const postShadowed = usePostShadow(post) const postShadowed = usePostShadow(post)
const richText = useMemo( const richText = useMemo(
@@ -122,6 +128,7 @@ export function PostFeedItem({
isParentBlocked={isParentBlocked} isParentBlocked={isParentBlocked}
isParentNotFound={isParentNotFound} isParentNotFound={isParentNotFound}
rootPost={rootPost} rootPost={rootPost}
onShowLess={onShowLess}
/> />
) )
} }
@@ -144,23 +151,27 @@ let FeedItemInner = ({
isParentBlocked, isParentBlocked,
isParentNotFound, isParentNotFound,
rootPost, rootPost,
onShowLess,
}: FeedItemProps & { }: FeedItemProps & {
richText: RichTextAPI richText: RichTextAPI
post: Shadow<AppBskyFeedDefs.PostView> post: Shadow<AppBskyFeedDefs.PostView>
rootPost: AppBskyFeedDefs.PostView rootPost: AppBskyFeedDefs.PostView
onShowLess?: (interaction: AppBskyFeedDefs.Interaction) => void
}): React.ReactNode => { }): React.ReactNode => {
const queryClient = useQueryClient() const queryClient = useQueryClient()
const {openComposer} = useComposerControls() const {openComposer} = useComposerControls()
const pal = usePalette('default') const pal = usePalette('default')
const {_} = useLingui() const {_} = useLingui()
const [hover, setHover] = useState(false)
const href = useMemo(() => { const href = useMemo(() => {
const urip = new AtUri(post.uri) const urip = new AtUri(post.uri)
return makeProfileLink(post.author, 'post', urip.rkey) return makeProfileLink(post.author, 'post', urip.rkey)
}, [post.uri, post.author]) }, [post.uri, post.author])
const {sendInteraction} = useFeedFeedbackContext() const {sendInteraction} = useFeedFeedbackContext()
const onPressReply = React.useCallback(() => { const onPressReply = useCallback(() => {
sendInteraction({ sendInteraction({
item: post.uri, item: post.uri,
event: 'app.bsky.feed.defs#interactionReply', event: 'app.bsky.feed.defs#interactionReply',
@@ -178,7 +189,7 @@ let FeedItemInner = ({
}) })
}, [post, record, openComposer, moderation, sendInteraction, feedContext]) }, [post, record, openComposer, moderation, sendInteraction, feedContext])
const onOpenAuthor = React.useCallback(() => { const onOpenAuthor = useCallback(() => {
sendInteraction({ sendInteraction({
item: post.uri, item: post.uri,
event: 'app.bsky.feed.defs#clickthroughAuthor', event: 'app.bsky.feed.defs#clickthroughAuthor',
@@ -186,7 +197,7 @@ let FeedItemInner = ({
}) })
}, [sendInteraction, post, feedContext]) }, [sendInteraction, post, feedContext])
const onOpenReposter = React.useCallback(() => { const onOpenReposter = useCallback(() => {
sendInteraction({ sendInteraction({
item: post.uri, item: post.uri,
event: 'app.bsky.feed.defs#clickthroughReposter', event: 'app.bsky.feed.defs#clickthroughReposter',
@@ -194,7 +205,7 @@ let FeedItemInner = ({
}) })
}, [sendInteraction, post, feedContext]) }, [sendInteraction, post, feedContext])
const onOpenEmbed = React.useCallback(() => { const onOpenEmbed = useCallback(() => {
sendInteraction({ sendInteraction({
item: post.uri, item: post.uri,
event: 'app.bsky.feed.defs#clickthroughEmbed', event: 'app.bsky.feed.defs#clickthroughEmbed',
@@ -202,7 +213,7 @@ let FeedItemInner = ({
}) })
}, [sendInteraction, post, feedContext]) }, [sendInteraction, post, feedContext])
const onBeforePress = React.useCallback(() => { const onBeforePress = useCallback(() => {
sendInteraction({ sendInteraction({
item: post.uri, item: post.uri,
event: 'app.bsky.feed.defs#clickthroughItem', event: 'app.bsky.feed.defs#clickthroughItem',
@@ -240,7 +251,6 @@ let FeedItemInner = ({
? rootPost.threadgate.record ? rootPost.threadgate.record
: undefined : undefined
const [hover, setHover] = useState(false)
return ( return (
<Link <Link
testID={`feedItem-by-${post.author.handle}`} testID={`feedItem-by-${post.author.handle}`}
@@ -427,6 +437,7 @@ let FeedItemInner = ({
logContext="FeedItem" logContext="FeedItem"
feedContext={feedContext} feedContext={feedContext}
threadgateRecord={threadgateRecord} threadgateRecord={threadgateRecord}
onShowLess={onShowLess}
/> />
</View> </View>
</View> </View>
@@ -461,7 +472,7 @@ let PostContent = ({
const threadgateHiddenReplies = useMergedThreadgateHiddenReplies({ const threadgateHiddenReplies = useMergedThreadgateHiddenReplies({
threadgateRecord, threadgateRecord,
}) })
const additionalPostAlerts: AppModerationCause[] = React.useMemo(() => { const additionalPostAlerts: AppModerationCause[] = useMemo(() => {
const isPostHiddenByThreadgate = threadgateHiddenReplies.has(post.uri) const isPostHiddenByThreadgate = threadgateHiddenReplies.has(post.uri)
const rootPostUri = bsky.dangerousIsType<AppBskyFeedPost.Record>( const rootPostUri = bsky.dangerousIsType<AppBskyFeedPost.Record>(
post.record, post.record,
@@ -482,7 +493,7 @@ let PostContent = ({
: [] : []
}, [post, currentAccount?.did, threadgateHiddenReplies]) }, [post, currentAccount?.did, threadgateHiddenReplies])
const onPressShowMore = React.useCallback(() => { const onPressShowMore = useCallback(() => {
setLimitLines(false) setLimitLines(false)
}, [setLimitLines]) }, [setLimitLines])
+46
View File
@@ -0,0 +1,46 @@
import {View} from 'react-native'
import {Trans} from '@lingui/macro'
import {atoms as a, useTheme} from '#/alf'
import {CircleCheck_Stroke2_Corner0_Rounded} from '#/components/icons/CircleCheck'
import {Text} from '#/components/Typography'
export function ShowLessFollowup() {
const t = useTheme()
return (
<View
style={[
t.atoms.border_contrast_low,
a.border_t,
t.atoms.bg_contrast_25,
a.p_sm,
]}>
<View
style={[
t.atoms.bg,
t.atoms.border_contrast_low,
a.border,
a.rounded_sm,
a.p_md,
a.flex_row,
a.gap_sm,
]}>
<CircleCheck_Stroke2_Corner0_Rounded
style={[t.atoms.text_contrast_low]}
size="sm"
/>
<Text
style={[
a.flex_1,
a.text_sm,
t.atoms.text_contrast_medium,
a.leading_snug,
]}>
<Trans>
Thank you for your feedback! It has been sent to the feed operator.
</Trans>
</Text>
</View>
</View>
)
}
+10 -6
View File
@@ -1,4 +1,4 @@
import React, {memo, useMemo, useState} from 'react' import {memo, useMemo, useState} from 'react'
import { import {
Pressable, Pressable,
type PressableProps, type PressableProps,
@@ -6,16 +6,17 @@ import {
type ViewStyle, type ViewStyle,
} from 'react-native' } from 'react-native'
import { import {
AppBskyFeedDefs, type AppBskyFeedDefs,
AppBskyFeedPost, type AppBskyFeedPost,
AppBskyFeedThreadgate, type AppBskyFeedThreadgate,
RichText as RichTextAPI, type RichText as RichTextAPI,
} from '@atproto/api' } from '@atproto/api'
import {msg} from '@lingui/macro' import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import type React from 'react'
import {useTheme} from '#/lib/ThemeContext' import {useTheme} from '#/lib/ThemeContext'
import {Shadow} from '#/state/cache/post-shadow' import {type Shadow} from '#/state/cache/post-shadow'
import {atoms as a, useTheme as useAlf} from '#/alf' import {atoms as a, useTheme as useAlf} from '#/alf'
import {DotGrid_Stroke2_Corner0_Rounded as DotsHorizontal} from '#/components/icons/DotGrid' import {DotGrid_Stroke2_Corner0_Rounded as DotsHorizontal} from '#/components/icons/DotGrid'
import {useMenuControl} from '#/components/Menu' import {useMenuControl} from '#/components/Menu'
@@ -34,6 +35,7 @@ let PostDropdownBtn = ({
size, size,
timestamp, timestamp,
threadgateRecord, threadgateRecord,
onShowLess,
}: { }: {
testID: string testID: string
post: Shadow<AppBskyFeedDefs.PostView> post: Shadow<AppBskyFeedDefs.PostView>
@@ -45,6 +47,7 @@ let PostDropdownBtn = ({
size?: 'lg' | 'md' | 'sm' size?: 'lg' | 'md' | 'sm'
timestamp: string timestamp: string
threadgateRecord?: AppBskyFeedThreadgate.Record threadgateRecord?: AppBskyFeedThreadgate.Record
onShowLess?: (interaction: AppBskyFeedDefs.Interaction) => void
}): React.ReactNode => { }): React.ReactNode => {
const theme = useTheme() const theme = useTheme()
const alf = useAlf() const alf = useAlf()
@@ -100,6 +103,7 @@ let PostDropdownBtn = ({
richText={richText} richText={richText}
timestamp={timestamp} timestamp={timestamp}
threadgateRecord={threadgateRecord} threadgateRecord={threadgateRecord}
onShowLess={onShowLess}
/> />
)} )}
</Menu.Root> </Menu.Root>
@@ -101,6 +101,7 @@ let PostDropdownMenuItems = ({
richText, richText,
timestamp, timestamp,
threadgateRecord, threadgateRecord,
onShowLess,
}: { }: {
testID: string testID: string
post: Shadow<AppBskyFeedDefs.PostView> post: Shadow<AppBskyFeedDefs.PostView>
@@ -112,6 +113,7 @@ let PostDropdownMenuItems = ({
size?: 'lg' | 'md' | 'sm' size?: 'lg' | 'md' | 'sm'
timestamp: string timestamp: string
threadgateRecord?: AppBskyFeedThreadgate.Record threadgateRecord?: AppBskyFeedThreadgate.Record
onShowLess?: (interaction: AppBskyFeedDefs.Interaction) => void
}): React.ReactNode => { }): React.ReactNode => {
const {hasSession, currentAccount} = useSession() const {hasSession, currentAccount} = useSession()
const {gtMobile} = useBreakpoints() const {gtMobile} = useBreakpoints()
@@ -303,8 +305,15 @@ let PostDropdownMenuItems = ({
item: postUri, item: postUri,
feedContext: postFeedContext, feedContext: postFeedContext,
}) })
if (onShowLess) {
onShowLess({
item: postUri,
feedContext: postFeedContext,
})
} else {
Toast.show(_(msg({message: 'Feedback sent!', context: 'toast'}))) Toast.show(_(msg({message: 'Feedback sent!', context: 'toast'})))
}, [feedFeedback, postUri, postFeedContext, _]) }
}, [feedFeedback, postUri, postFeedContext, _, onShowLess])
const onSelectChatToShareTo = React.useCallback( const onSelectChatToShareTo = React.useCallback(
(conversation: string) => { (conversation: string) => {
+8 -5
View File
@@ -8,11 +8,11 @@ import {
} from 'react-native' } from 'react-native'
import * as Clipboard from 'expo-clipboard' import * as Clipboard from 'expo-clipboard'
import { import {
AppBskyFeedDefs, type AppBskyFeedDefs,
AppBskyFeedPost, type AppBskyFeedPost,
AppBskyFeedThreadgate, type AppBskyFeedThreadgate,
AtUri, AtUri,
RichText as RichTextAPI, type RichText as RichTextAPI,
} from '@atproto/api' } from '@atproto/api'
import {msg, plural} from '@lingui/macro' import {msg, plural} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
@@ -26,7 +26,7 @@ import {makeProfileLink} from '#/lib/routes/links'
import {shareUrl} from '#/lib/sharing' import {shareUrl} from '#/lib/sharing'
import {useGate} from '#/lib/statsig/statsig' import {useGate} from '#/lib/statsig/statsig'
import {toShareUrl} from '#/lib/strings/url-helpers' import {toShareUrl} from '#/lib/strings/url-helpers'
import {Shadow} from '#/state/cache/types' import {type Shadow} from '#/state/cache/types'
import {useFeedFeedbackContext} from '#/state/feed-feedback' import {useFeedFeedbackContext} from '#/state/feed-feedback'
import { import {
usePostLikeMutationQueue, usePostLikeMutationQueue,
@@ -60,6 +60,7 @@ let PostCtrls = ({
onPostReply, onPostReply,
logContext, logContext,
threadgateRecord, threadgateRecord,
onShowLess,
}: { }: {
big?: boolean big?: boolean
post: Shadow<AppBskyFeedDefs.PostView> post: Shadow<AppBskyFeedDefs.PostView>
@@ -71,6 +72,7 @@ let PostCtrls = ({
onPostReply?: (postUri: string | undefined) => void onPostReply?: (postUri: string | undefined) => void
logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo' logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo'
threadgateRecord?: AppBskyFeedThreadgate.Record threadgateRecord?: AppBskyFeedThreadgate.Record
onShowLess?: (interaction: AppBskyFeedDefs.Interaction) => void
}): React.ReactNode => { }): React.ReactNode => {
const t = useTheme() const t = useTheme()
const {_, i18n} = useLingui() const {_, i18n} = useLingui()
@@ -378,6 +380,7 @@ let PostCtrls = ({
hitSlop={POST_CTRL_HITSLOP} hitSlop={POST_CTRL_HITSLOP}
timestamp={post.indexedAt} timestamp={post.indexedAt}
threadgateRecord={threadgateRecord} threadgateRecord={threadgateRecord}
onShowLess={onShowLess}
/> />
</View> </View>
{isDiscoverDebugUser && feedContext && ( {isDiscoverDebugUser && feedContext && (