forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {View} from 'react-native'
2import {AppBskyEmbedVideo} from '@atproto/api'
3
4import {type FeedPostSliceItem} from '#/state/queries/post-feed'
5import {type VideoFeedSourceContext} from '#/screens/VideoFeed/types'
6import {atoms as a, useGutters} from '#/alf'
7import * as Grid from '#/components/Grid'
8import {
9 VideoPostCard,
10 VideoPostCardPlaceholder,
11} from '#/components/VideoPostCard'
12import {useAnalytics} from '#/analytics'
13
14export function PostFeedVideoGridRow({
15 items: slices,
16 sourceContext,
17}: {
18 items: FeedPostSliceItem[]
19 sourceContext: VideoFeedSourceContext
20}) {
21 const ax = useAnalytics()
22 const gutters = useGutters(['base', 'base', 0, 'base'])
23 const posts = slices
24 .filter(slice => AppBskyEmbedVideo.isView(slice.post.embed))
25 .map(slice => ({
26 post: slice.post,
27 moderation: slice.moderation,
28 }))
29
30 /**
31 * This should not happen because we should be filtering out posts without
32 * videos within the `PostFeed` component.
33 */
34 if (posts.length !== slices.length) return null
35
36 return (
37 <View style={[gutters]}>
38 <View style={[a.flex_row, a.gap_sm]}>
39 <Grid.Row gap={a.gap_sm.gap}>
40 {posts.map(post => (
41 <Grid.Col key={post.post.uri} width={1 / 2}>
42 <VideoPostCard
43 post={post.post}
44 sourceContext={sourceContext}
45 moderation={post.moderation}
46 onInteract={() => {
47 ax.metric('videoCard:click', {context: 'feed'})
48 }}
49 />
50 </Grid.Col>
51 ))}
52 </Grid.Row>
53 </View>
54 </View>
55 )
56}
57
58export function PostFeedVideoGridRowPlaceholder() {
59 const gutters = useGutters(['base', 'base', 0, 'base'])
60 return (
61 <View style={[gutters]}>
62 <View style={[a.flex_row, a.gap_sm]}>
63 <VideoPostCardPlaceholder />
64 <VideoPostCardPlaceholder />
65 </View>
66 </View>
67 )
68}