import {useCallback, useRef, useState} from 'react'
import {
type HostInstance,
ScrollView,
type ScrollViewImperativeMethods,
useWindowDimensions,
View,
} from 'react-native'
import {LinearGradient} from 'expo-linear-gradient'
import {Plural, useLingui} from '@lingui/react/macro'
import {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons'
import {type FeedPostSlice} from '#/state/queries/post-feed'
import {BlockDrawerGesture} from '#/view/shell/BlockDrawerGesture'
import {atoms as a, useTheme, utils, web} from '#/alf'
import {Button, ButtonIcon} from '#/components/Button'
import {
ChevronBottom_Stroke2_Corner0_Rounded as ChevronBottom,
ChevronLeft_Stroke2_Corner0_Rounded as ChevronLeft,
ChevronRight_Stroke2_Corner0_Rounded as ChevronRight,
ChevronTop_Stroke2_Corner0_Rounded as ChevronTop,
} from '#/components/icons/Chevron'
import {GalleryBleed} from '#/components/images/Gallery'
import {ITEM_GAP} from '#/components/images/Gallery/const'
import {tween} from '#/components/images/Gallery/tween'
import {useKeyboardHandlers} from '#/components/images/Gallery/useKeyboardHandlers'
import {usePointerHandlers} from '#/components/images/Gallery/usePointerHandlers'
import {getOffsetForIndex} from '#/components/images/Gallery/utils'
import {Text} from '#/components/Typography'
import {IS_WEB} from '#/env'
import {PostFeedItem} from './PostFeedItem'
const CARD_WIDTH = 320
const CARD_INTERVAL = CARD_WIDTH + ITEM_GAP
const SETTLE_DURATION = 700
const MAX_CAROUSEL_HEIGHT = 520
const CAROUSEL_VIEWPORT_RATIO = 0.55
const BOTTOM_FADE_HEIGHT = 96
function RepostCarouselViewport({
children,
expanded,
}: {
children: React.ReactNode
expanded: boolean
}) {
const t = useTheme()
const {height} = useWindowDimensions()
const maxHeight = Math.min(
MAX_CAROUSEL_HEIGHT,
height * CAROUSEL_VIEWPORT_RATIO,
)
return (
{children}
{!expanded && (
)}
)
}
function RepostCard({
slice,
itemRef,
}: {
slice: FeedPostSlice
itemRef?: (node: HostInstance | null) => void
}) {
const t = useTheme()
const item = slice.items[0]
/*
* GalleryBleed sizes nested image carousels to this card instead of the
* viewport. It also applies overflow: hidden for border-radius clipping.
*/
return (
)
}
function RepostCarouselHeader({
count,
expanded,
onToggleExpanded,
onScrollLeft,
onScrollRight,
}: {
count: number
expanded: boolean
onToggleExpanded: () => void
onScrollLeft: () => void
onScrollRight: () => void
}) {
const t = useTheme()
const {t: l} = useLingui()
const enableSquareButtons = useEnableSquareButtons()
return (
{count}
)
}
function RepostCarouselNative({
items,
expanded,
onToggleExpanded,
}: {
items: FeedPostSlice[]
expanded: boolean
onToggleExpanded: () => void
}) {
const scrollRef = useRef<(HostInstance & ScrollViewImperativeMethods) | null>(
null,
)
const currentIndexRef = useRef(0)
const scrollToIndex = useCallback((index: number) => {
currentIndexRef.current = index
scrollRef.current?.scrollTo({
x: index * CARD_INTERVAL,
y: 0,
animated: true,
})
}, [])
const scrollLeft = useCallback(() => {
const current = currentIndexRef.current
const next = current > 0 ? current - 1 : items.length - 1
scrollToIndex(next)
}, [items.length, scrollToIndex])
const scrollRight = useCallback(() => {
const current = currentIndexRef.current
const next = current < items.length - 1 ? current + 1 : 0
scrollToIndex(next)
}, [items.length, scrollToIndex])
return (
<>
{
currentIndexRef.current = Math.round(
e.nativeEvent.contentOffset.x / CARD_INTERVAL,
)
}}
contentContainerStyle={[a.px_md, a.pt_sm, a.pb_lg]}>
{items.map(slice => (
))}
>
)
}
function RepostCarouselWeb({
items,
expanded,
onToggleExpanded,
}: {
items: FeedPostSlice[]
expanded: boolean
onToggleExpanded: () => void
}) {
const {t: l} = useLingui()
const scrollRef = useRef<(HostInstance & ScrollViewImperativeMethods) | null>(
null,
)
const itemWidthsRef = useRef