[APP-1934] replace image grid layout with carousel (#10157)
Co-authored-by: RetroSunstar <57507616+RetroSunstar@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Eric Bailey <git@esb.lol>
This commit is contained in:
+158
-139
@@ -34,6 +34,10 @@ import {Link} from '#/view/com/util/Link'
|
||||
import {PostMeta} from '#/view/com/util/PostMeta'
|
||||
import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar'
|
||||
import {atoms as a} from '#/alf'
|
||||
import {
|
||||
GalleryBleed,
|
||||
maybeApplyGalleryOffsetStyles,
|
||||
} from '#/components/images/Gallery'
|
||||
import {ContentHider} from '#/components/moderation/ContentHider'
|
||||
import {LabelsOnMyPost} from '#/components/moderation/LabelsOnMe'
|
||||
import {PostAlerts} from '#/components/moderation/PostAlerts'
|
||||
@@ -163,6 +167,7 @@ let FeedItemInner = ({
|
||||
const queryClient = useQueryClient()
|
||||
const {openComposer} = useOpenComposer()
|
||||
const pal = usePalette('default')
|
||||
const {currentAccount} = useSession()
|
||||
|
||||
const [hover, setHover] = useState(false)
|
||||
|
||||
@@ -293,140 +298,6 @@ let FeedItemInner = ({
|
||||
}
|
||||
}, [reason])
|
||||
|
||||
return (
|
||||
<Link
|
||||
testID={`feedItem-by-${post.author.handle}`}
|
||||
style={outerStyles}
|
||||
href={href}
|
||||
noFeedback
|
||||
accessible={false}
|
||||
onBeforePress={onBeforePress}
|
||||
dataSet={{feedContext}}
|
||||
onPointerEnter={() => {
|
||||
setHover(true)
|
||||
}}
|
||||
onPointerLeave={() => {
|
||||
setHover(false)
|
||||
}}>
|
||||
<SubtleHover hover={hover} />
|
||||
<View style={{flexDirection: 'row', gap: 10, paddingLeft: 8}}>
|
||||
<View style={{width: 42}}>
|
||||
{isThreadChild && (
|
||||
<View
|
||||
style={[
|
||||
styles.replyLine,
|
||||
{
|
||||
flexGrow: 1,
|
||||
backgroundColor: pal.colors.replyLine,
|
||||
marginBottom: 4,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<View style={[a.pt_sm, a.flex_shrink]}>
|
||||
{reason && (
|
||||
<PostFeedReason
|
||||
reason={reason}
|
||||
moderation={moderation}
|
||||
onOpenReposter={onOpenReposter}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.layout}>
|
||||
<View style={styles.layoutAvi}>
|
||||
<PreviewableUserAvatar
|
||||
size={42}
|
||||
profile={post.author}
|
||||
moderation={moderation.ui('avatar')}
|
||||
type={post.author.associated?.labeler ? 'labeler' : 'user'}
|
||||
onBeforePress={onOpenAuthor}
|
||||
live={live}
|
||||
/>
|
||||
{isThreadParent && (
|
||||
<View
|
||||
style={[
|
||||
styles.replyLine,
|
||||
{
|
||||
flexGrow: 1,
|
||||
backgroundColor: pal.colors.replyLine,
|
||||
marginTop: live ? 8 : 4,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.layoutContent}>
|
||||
<PostMeta
|
||||
author={post.author}
|
||||
moderation={moderation}
|
||||
timestamp={post.indexedAt}
|
||||
postHref={href}
|
||||
onOpenAuthor={onOpenAuthor}
|
||||
/>
|
||||
{showReplyTo &&
|
||||
(parentAuthor || isParentBlocked || isParentNotFound) && (
|
||||
<PostRepliedTo
|
||||
parentAuthor={parentAuthor}
|
||||
isParentBlocked={isParentBlocked}
|
||||
isParentNotFound={isParentNotFound}
|
||||
/>
|
||||
)}
|
||||
<LabelsOnMyPost post={post} />
|
||||
<PostContent
|
||||
moderation={moderation}
|
||||
richText={richText}
|
||||
postEmbed={post.embed}
|
||||
postAuthor={post.author}
|
||||
onOpenEmbed={onOpenEmbed}
|
||||
post={post}
|
||||
threadgateRecord={threadgateRecord}
|
||||
/>
|
||||
<PostControls
|
||||
post={post}
|
||||
record={record}
|
||||
richText={richText}
|
||||
onPressReply={onPressReply}
|
||||
logContext="FeedItem"
|
||||
feedContext={feedContext}
|
||||
reqId={reqId}
|
||||
threadgateRecord={threadgateRecord}
|
||||
onShowLess={onShowLess}
|
||||
viaRepost={viaRepost}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<DiscoverDebug feedContext={feedContext} />
|
||||
</View>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
FeedItemInner = memo(FeedItemInner)
|
||||
|
||||
let PostContent = ({
|
||||
post,
|
||||
moderation,
|
||||
richText,
|
||||
postEmbed,
|
||||
postAuthor,
|
||||
onOpenEmbed,
|
||||
threadgateRecord,
|
||||
}: {
|
||||
moderation: ModerationDecision
|
||||
richText: RichTextAPI
|
||||
postEmbed: AppBskyFeedDefs.PostView['embed']
|
||||
postAuthor: AppBskyFeedDefs.PostView['author']
|
||||
onOpenEmbed: () => void
|
||||
post: AppBskyFeedDefs.PostView
|
||||
threadgateRecord?: AppBskyFeedThreadgate.Record
|
||||
}): React.ReactNode => {
|
||||
const {currentAccount} = useSession()
|
||||
const [limitLines, setLimitLines] = useState(
|
||||
() => countLines(richText.text) >= MAX_POST_LINES,
|
||||
)
|
||||
const threadgateHiddenReplies = useMergedThreadgateHiddenReplies({
|
||||
threadgateRecord,
|
||||
})
|
||||
@@ -451,6 +322,150 @@ let PostContent = ({
|
||||
: []
|
||||
}, [post, currentAccount?.did, threadgateHiddenReplies])
|
||||
|
||||
return (
|
||||
<GalleryBleed>
|
||||
<Link
|
||||
testID={`feedItem-by-${post.author.handle}`}
|
||||
style={outerStyles}
|
||||
href={href}
|
||||
noFeedback
|
||||
accessible={false}
|
||||
onBeforePress={onBeforePress}
|
||||
dataSet={{feedContext}}
|
||||
onPointerEnter={() => {
|
||||
setHover(true)
|
||||
}}
|
||||
onPointerLeave={() => {
|
||||
setHover(false)
|
||||
}}>
|
||||
<SubtleHover hover={hover} />
|
||||
<View style={{flexDirection: 'row', gap: 10, paddingLeft: 8}}>
|
||||
<View style={{width: 42}}>
|
||||
{isThreadChild && (
|
||||
<View
|
||||
style={[
|
||||
styles.replyLine,
|
||||
{
|
||||
flexGrow: 1,
|
||||
backgroundColor: pal.colors.replyLine,
|
||||
marginBottom: 4,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<View style={[a.pt_sm, a.flex_shrink]}>
|
||||
{reason && (
|
||||
<PostFeedReason
|
||||
reason={reason}
|
||||
moderation={moderation}
|
||||
onOpenReposter={onOpenReposter}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.layout}>
|
||||
<View style={styles.layoutAvi}>
|
||||
<PreviewableUserAvatar
|
||||
size={42}
|
||||
profile={post.author}
|
||||
moderation={moderation.ui('avatar')}
|
||||
type={post.author.associated?.labeler ? 'labeler' : 'user'}
|
||||
onBeforePress={onOpenAuthor}
|
||||
live={live}
|
||||
/>
|
||||
{isThreadParent && (
|
||||
<View
|
||||
style={[
|
||||
styles.replyLine,
|
||||
{
|
||||
flexGrow: 1,
|
||||
backgroundColor: pal.colors.replyLine,
|
||||
marginTop: live ? 8 : 4,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
<View
|
||||
style={[
|
||||
styles.layoutContent,
|
||||
maybeApplyGalleryOffsetStyles('meta', {
|
||||
post,
|
||||
modui: moderation.ui('contentList'),
|
||||
additionalCauses: additionalPostAlerts,
|
||||
}),
|
||||
]}>
|
||||
<PostMeta
|
||||
author={post.author}
|
||||
moderation={moderation}
|
||||
timestamp={post.indexedAt}
|
||||
postHref={href}
|
||||
onOpenAuthor={onOpenAuthor}
|
||||
/>
|
||||
{showReplyTo &&
|
||||
(parentAuthor || isParentBlocked || isParentNotFound) && (
|
||||
<PostRepliedTo
|
||||
parentAuthor={parentAuthor}
|
||||
isParentBlocked={isParentBlocked}
|
||||
isParentNotFound={isParentNotFound}
|
||||
/>
|
||||
)}
|
||||
<LabelsOnMyPost post={post} />
|
||||
<PostContent
|
||||
moderation={moderation}
|
||||
richText={richText}
|
||||
postEmbed={post.embed}
|
||||
postAuthor={post.author}
|
||||
onOpenEmbed={onOpenEmbed}
|
||||
post={post}
|
||||
additionalPostAlerts={additionalPostAlerts}
|
||||
/>
|
||||
<PostControls
|
||||
post={post}
|
||||
record={record}
|
||||
richText={richText}
|
||||
onPressReply={onPressReply}
|
||||
logContext="FeedItem"
|
||||
feedContext={feedContext}
|
||||
reqId={reqId}
|
||||
threadgateRecord={threadgateRecord}
|
||||
onShowLess={onShowLess}
|
||||
viaRepost={viaRepost}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<DiscoverDebug feedContext={feedContext} />
|
||||
</View>
|
||||
</Link>
|
||||
</GalleryBleed>
|
||||
)
|
||||
}
|
||||
FeedItemInner = memo(FeedItemInner)
|
||||
|
||||
let PostContent = ({
|
||||
post,
|
||||
moderation,
|
||||
richText,
|
||||
postEmbed,
|
||||
postAuthor,
|
||||
onOpenEmbed,
|
||||
additionalPostAlerts,
|
||||
}: {
|
||||
moderation: ModerationDecision
|
||||
richText: RichTextAPI
|
||||
postEmbed: AppBskyFeedDefs.PostView['embed']
|
||||
postAuthor: AppBskyFeedDefs.PostView['author']
|
||||
onOpenEmbed: () => void
|
||||
post: AppBskyFeedDefs.PostView
|
||||
additionalPostAlerts?: AppModerationCause[]
|
||||
}): React.ReactNode => {
|
||||
const [limitLines, setLimitLines] = useState(
|
||||
() => countLines(richText.text) >= MAX_POST_LINES,
|
||||
)
|
||||
|
||||
const record = useMemo<AppBskyFeedPost.Record | undefined>(
|
||||
() =>
|
||||
bsky.validate(post.record, AppBskyFeedPost.validateRecord)
|
||||
@@ -492,7 +507,15 @@ let PostContent = ({
|
||||
) : undefined}
|
||||
{record && <TranslatedPost hideTranslateLink post={post} />}
|
||||
{postEmbed ? (
|
||||
<View style={[a.pb_xs]}>
|
||||
<View
|
||||
style={[
|
||||
a.pb_xs,
|
||||
maybeApplyGalleryOffsetStyles('embed', {
|
||||
post,
|
||||
modui: moderation.ui('contentList'),
|
||||
additionalCauses: additionalPostAlerts,
|
||||
}),
|
||||
]}>
|
||||
<Embed
|
||||
embed={postEmbed}
|
||||
moderation={moderation}
|
||||
@@ -524,13 +547,9 @@ const styles = StyleSheet.create({
|
||||
layoutAvi: {
|
||||
paddingLeft: 8,
|
||||
paddingRight: 10,
|
||||
position: 'relative',
|
||||
zIndex: 999,
|
||||
},
|
||||
layoutContent: {
|
||||
position: 'relative',
|
||||
flex: 1,
|
||||
zIndex: 0,
|
||||
},
|
||||
alert: {
|
||||
marginTop: 6,
|
||||
|
||||
Reference in New Issue
Block a user