Add grid
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
import {Pressable,View} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {LinearGradient} from 'expo-linear-gradient'
|
||||
import {AppBskyEmbedVideo} from '@atproto/api'
|
||||
import {msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||
import {FeedPostSliceItem} from '#/state/queries/post-feed'
|
||||
import {formatCount} from '#/view/com/util/numeric/format'
|
||||
import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {BLUE_HUE} from '#/alf/util/colorGeneration'
|
||||
import {select} from '#/alf/util/themeSelector'
|
||||
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
||||
import {Heart2_Stroke2_Corner0_Rounded as Heart} from '#/components/icons/Heart2'
|
||||
import {Repost_Stroke2_Corner2_Rounded as Repost} from '#/components/icons/Repost'
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
export function VideoPostCard({post}: {post: FeedPostSliceItem}) {
|
||||
const t = useTheme()
|
||||
const {_, i18n} = useLingui()
|
||||
const embed = post.post.embed
|
||||
const {
|
||||
state: hovered,
|
||||
onIn: onHoverIn,
|
||||
onOut: onHoverOut,
|
||||
} = useInteractionState()
|
||||
|
||||
if (!AppBskyEmbedVideo.isView(embed)) {
|
||||
// TODO unavailable?
|
||||
return null
|
||||
}
|
||||
|
||||
const {thumbnail} = embed
|
||||
const black = select(t.name, {
|
||||
light: t.atoms.bg_contrast_25.backgroundColor,
|
||||
dark: t.atoms.bg_contrast_25.backgroundColor,
|
||||
dim: `hsl(${BLUE_HUE}, 28%, 6%)`,
|
||||
})
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
accessibilityHint={_(msg`View video`)} // TODO
|
||||
accessibilityLabel={_(msg`View video`)}
|
||||
onHoverIn={onHoverIn}
|
||||
onHoverOut={onHoverOut}>
|
||||
<View
|
||||
style={[
|
||||
a.justify_center,
|
||||
a.rounded_sm,
|
||||
a.overflow_hidden,
|
||||
{
|
||||
backgroundColor: black,
|
||||
aspectRatio: 9 / 16,
|
||||
},
|
||||
]}>
|
||||
<Image
|
||||
source={{uri: thumbnail}}
|
||||
style={[a.w_full, a.h_full]}
|
||||
accessibilityIgnoresInvertColors
|
||||
/>
|
||||
|
||||
<View style={[a.absolute, a.inset_0]}>
|
||||
<View
|
||||
style={[
|
||||
a.absolute,
|
||||
a.inset_0,
|
||||
a.transition_opacity,
|
||||
{
|
||||
backgroundColor: black,
|
||||
opacity: hovered ? 0 : 0.2,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<View
|
||||
style={[
|
||||
a.absolute,
|
||||
a.inset_0,
|
||||
a.pt_3xl,
|
||||
{
|
||||
top: 'auto',
|
||||
},
|
||||
]}>
|
||||
<LinearGradient
|
||||
colors={[black, 'rgba(22, 24, 35, 0)']}
|
||||
locations={[0.02, 1]}
|
||||
start={{x: 0, y: 1}}
|
||||
end={{x: 0, y: 0}}
|
||||
style={[a.absolute, a.inset_0]}
|
||||
/>
|
||||
|
||||
<View style={[a.relative, a.z_10, a.p_md, a.flex_row, a.gap_md]}>
|
||||
<View style={[a.flex_row, a.align_center, a.gap_xs]}>
|
||||
<Heart size="md" fill="white" />
|
||||
<Text style={[a.text_md, a.font_bold]}>
|
||||
{formatCount(i18n, post.post.likeCount || 0)}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={[a.flex_row, a.align_center, a.gap_xs]}>
|
||||
<Repost size="md" fill="white" />
|
||||
<Text style={[a.text_md, a.font_bold]}>
|
||||
{formatCount(i18n, post.post.repostCount || 0)}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<View style={[a.pt_sm, a.flex_row, a.gap_sm, a.align_center]}>
|
||||
<PreviewableUserAvatar
|
||||
type="user"
|
||||
size={24}
|
||||
profile={post.post.author}
|
||||
/>
|
||||
<Text
|
||||
style={[
|
||||
a.flex_1,
|
||||
a.text_sm,
|
||||
a.font_bold,
|
||||
a.leading_tight,
|
||||
t.atoms.text_contrast_medium,
|
||||
]}
|
||||
numberOfLines={1}>
|
||||
{sanitizeHandle(post.post.author.handle, '@')}
|
||||
</Text>
|
||||
</View>
|
||||
</Pressable>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import {View} from 'react-native'
|
||||
|
||||
import {FeedPostSliceItem} from '#/state/queries/post-feed'
|
||||
import {atoms as a, useGutters} from '#/alf'
|
||||
import {VideoPostCard} from '#/components/VideoPostCard'
|
||||
|
||||
export function PostFeedVideoGridRow({posts}: {posts: FeedPostSliceItem[]}) {
|
||||
const gutters = useGutters(['base', 'base', 0, 'base'])
|
||||
return (
|
||||
<View style={[gutters]}>
|
||||
<View style={[a.flex_row, a.gap_lg]}>
|
||||
{posts.map(post => (
|
||||
<View key={post._reactKey} style={[a.flex_1]}>
|
||||
<VideoPostCard post={post} />
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user