diff --git a/src/components/VideoPostCard.tsx b/src/components/VideoPostCard.tsx
index cc4d3124cd..e5137d84fe 100644
--- a/src/components/VideoPostCard.tsx
+++ b/src/components/VideoPostCard.tsx
@@ -1,30 +1,40 @@
import {View} from 'react-native'
import {Image} from 'expo-image'
import {LinearGradient} from 'expo-linear-gradient'
-import {AppBskyEmbedVideo, AppBskyFeedDefs, AppBskyFeedPost} from '@atproto/api'
+import {
+ AppBskyActorDefs,
+ AppBskyEmbedVideo,
+ AppBskyFeedDefs,
+ AppBskyFeedPost,
+ ModerationDecision,
+} from '@atproto/api'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {sanitizeHandle} from '#/lib/strings/handles'
import {formatCount} from '#/view/com/util/numeric/format'
-import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar'
+import {UserAvatar} from '#/view/com/util/UserAvatar'
import {VideoFeedSourceContext} from '#/screens/VideoFeed/types'
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 {EyeSlash_Stroke2_Corner0_Rounded as Eye} from '#/components/icons/EyeSlash'
import {Heart2_Stroke2_Corner0_Rounded as Heart} from '#/components/icons/Heart2'
import {Repost_Stroke2_Corner2_Rounded as Repost} from '#/components/icons/Repost'
import {Link} from '#/components/Link'
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
+import * as Hider from '#/components/moderation/Hider'
import {Text} from '#/components/Typography'
export function VideoPostCard({
post,
sourceContext,
+ moderation,
}: {
post: AppBskyFeedDefs.PostView
sourceContext: VideoFeedSourceContext
+ moderation: ModerationDecision
}) {
const t = useTheme()
const {_, i18n} = useLingui()
@@ -70,82 +80,129 @@ export function VideoPostCard({
justifyContent: undefined,
},
]}>
-
-
-
-
-
+
+
-
-
-
- {likeCount > 0 && (
-
-
-
- {formatCount(i18n, likeCount)}
-
-
- )}
- {repostCount > 0 && (
-
-
-
- {formatCount(i18n, repostCount)}
-
-
- )}
+
+
+
+
+
+
+ {_(msg`Hidden`)}
+
+
-
-
-
- {text && (
-
- {text}
-
- )}
-
-
-
+
+
+
- {sanitizeHandle(post.author.handle, '@')}
-
-
-
+ a.justify_center,
+ a.rounded_md,
+ a.overflow_hidden,
+ {
+ backgroundColor: black,
+ aspectRatio: 9 / 16,
+ },
+ ]}>
+
+
+
+
+
+
+
+
+ {likeCount > 0 && (
+
+
+
+ {formatCount(i18n, likeCount)}
+
+
+ )}
+ {repostCount > 0 && (
+
+
+
+ {formatCount(i18n, repostCount)}
+
+
+ )}
+
+
+
+
+
+ {text && (
+
+ {text}
+
+ )}
+
+
+
+ {sanitizeHandle(post.author.handle, '@')}
+
+
+
+
+
)
}
@@ -171,6 +228,20 @@ export function VideoPostCardPlaceholder() {
]}>
+
+
+ )
+}
+
+export function VideoPostCardTextPlaceholder({
+ author,
+}: {
+ author?: AppBskyActorDefs.ProfileViewBasic
+}) {
+ const t = useTheme()
+
+ return (
+
-
-
-
-
+ {author ? (
+
+
+
+ {sanitizeHandle(author.handle, '@')}
+
+
+ ) : (
+
+
+
+
+ )}
)
diff --git a/src/components/feeds/PostFeedVideoGridRow.tsx b/src/components/feeds/PostFeedVideoGridRow.tsx
index d708dc95bf..88a03ddaa3 100644
--- a/src/components/feeds/PostFeedVideoGridRow.tsx
+++ b/src/components/feeds/PostFeedVideoGridRow.tsx
@@ -19,7 +19,10 @@ export function PostFeedVideoGridRow({
const gutters = useGutters(['base', 'base', 0, 'base'])
const posts = slices
.filter(slice => AppBskyEmbedVideo.isView(slice.post.embed))
- .map(slice => slice.post)
+ .map(slice => ({
+ post: slice.post,
+ moderation: slice.moderation,
+ }))
/**
* This should not happen because we should be filtering out posts without
@@ -31,8 +34,12 @@ export function PostFeedVideoGridRow({
{posts.map(post => (
-
-
+
+
))}
diff --git a/src/view/com/posts/PostFeed.tsx b/src/view/com/posts/PostFeed.tsx
index 8bb9d7162c..84edfcf630 100644
--- a/src/view/com/posts/PostFeed.tsx
+++ b/src/view/com/posts/PostFeed.tsx
@@ -323,37 +323,44 @@ let PostFeed = ({
})
} else if (data) {
let sliceIndex = -1
- for (const page of data?.pages) {
- if (isVideoFeed && isNative) {
- const rows: FeedPostSliceItem[][] = []
- for (let i = 0; i < page.slices.length; i++) {
- const slice = page.slices[i]
- const root = slice.items.at(0)
- if (!root) continue
- // TODO test this
- if (!AppBskyEmbedVideo.isView(root.post.embed)) {
- i--
- continue
- }
- const cols = gtMobile ? 3 : 2
- if (i % cols === 0) {
- rows.push([root])
- } else {
- rows[rows.length - 1].push(root)
- }
- }
- for (const row of rows) {
- sliceIndex++
-
- arr.push({
- type: 'videoGridRow',
- key: row.map(r => r._reactKey).join('-'),
- slices: row,
- sourceFeedUri: feedUri,
- })
+ if (isVideoFeed && isNative) {
+ const rows: FeedPostSliceItem[][] = []
+ let slices: {slice: FeedPostSlice; index: number}[] = []
+ for (const page of data.pages) {
+ for (const slice of page.slices) {
+ slices.push({slice, index: sliceIndex++})
}
- } else {
+ }
+
+ for (let i = 0; i < slices.length; i++) {
+ const slice = slices[i]
+ const root = slice.slice.items.at(0)
+ if (!root) continue
+ // TODO test this
+ if (!AppBskyEmbedVideo.isView(root.post.embed)) {
+ i--
+ continue
+ }
+ const cols = gtMobile ? 3 : 2
+ if (i % cols === 0) {
+ rows.push([root])
+ } else {
+ rows[rows.length - 1].push(root)
+ }
+ }
+
+ for (const row of rows) {
+ sliceIndex++
+ arr.push({
+ type: 'videoGridRow',
+ key: row.map(r => r._reactKey).join('-'),
+ slices: row,
+ sourceFeedUri: feedUri,
+ })
+ }
+ } else {
+ for (const page of data?.pages) {
for (const slice of page.slices) {
sliceIndex++