From e466bf6b5cbe77ca054433a9a025968d8c5bcb5e Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Fri, 17 Jan 2025 16:47:46 +0000 Subject: [PATCH] cleanup attempt --- src/screens/Feeds/VibeScreen.tsx | 416 ++++++++++++++++--------------- 1 file changed, 210 insertions(+), 206 deletions(-) diff --git a/src/screens/Feeds/VibeScreen.tsx b/src/screens/Feeds/VibeScreen.tsx index b80a43e0ca..a6cc0910cb 100644 --- a/src/screens/Feeds/VibeScreen.tsx +++ b/src/screens/Feeds/VibeScreen.tsx @@ -22,8 +22,8 @@ import Animated, { withTiming, } from 'react-native-reanimated' import {SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context' -import {useEvent, useEventListener} from 'expo' -import {Image} from 'expo-image' +import {useEventListener} from 'expo' +import {Image, ImageStyle} from 'expo-image' import {LinearGradient} from 'expo-linear-gradient' import {createVideoPlayer, VideoPlayer, VideoView} from 'expo-video' import { @@ -49,7 +49,6 @@ import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' import {CommonNavigatorParams, NavigationProp} from '#/lib/routes/types' import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeHandle} from '#/lib/strings/handles' -import {isAndroid} from '#/platform/detection' import {POST_TOMBSTONE, Shadow, usePostShadow} from '#/state/cache/post-shadow' import {usePostLikeMutationQueue} from '#/state/queries/post' import {FeedPostSliceItem, usePostFeedQuery} from '#/state/queries/post-feed' @@ -58,13 +57,12 @@ import {useSetLightStatusBar} from '#/state/shell/light-status-bar' import {List} from '#/view/com/util/List' import {PostCtrls} from '#/view/com/util/post-ctrls/PostCtrls' import {formatTime} from '#/view/com/util/post-embeds/VideoEmbedInner/web-controls/utils' -import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar' +import {UserAvatar} from '#/view/com/util/UserAvatar' import {Header} from '#/screens/VideoFeed/Header' import {atoms as a, ThemeProvider, tokens, useTheme} from '#/alf' import {Button, ButtonText} from '#/components/Button' import * as Layout from '#/components/Layout' import {ListFooter} from '#/components/Lists' -import {Loader} from '#/components/Loader' import {RichText} from '#/components/RichText' import {Text} from '#/components/Typography' @@ -361,46 +359,11 @@ function VideoItem({ }) { const postShadow = usePostShadow(post) const {height, width} = useWindowDimensions() - const insets = useSafeAreaInsets() return ( - + - {player ? ( - - ) : ( - embed.thumbnail && ( - - ) - )} - {postShadow !== POST_TOMBSTONE ? ( - player && ( - - ) - ) : ( + {postShadow === POST_TOMBSTONE ? ( Post has been deleted + ) : ( + <> + + {player && ( + + )} + + )} ) } +// TODO maybe unused function VideoItemInner({ player, embed, @@ -436,44 +413,27 @@ function VideoItemInner({ embed: AppBskyEmbedVideo.View active: boolean }) { - const insets = useSafeAreaInsets() - const {status} = useEvent(player, 'statusChange', {status: player.status}) - - const videoAspectRatio = - (embed.aspectRatio?.width ?? 1) / (embed.aspectRatio?.height ?? 1) - - // if the video tall enough (tiktok/reels are 9:16) go cover mode - const isCloseEnough = videoAspectRatio <= 9 / 16 + // const {status} = useEvent(player, 'statusChange', {status: player.status}) return ( <> + {/* + + */} + {active && player && ( )} - {embed.thumbnail && ( - - )} ) } @@ -484,42 +444,20 @@ function Overlay({ active, scrollGesture, }: { - player: VideoPlayer + player?: VideoPlayer post: Shadow active: boolean scrollGesture: NativeGesture }) { - const insets = useSafeAreaInsets() const t = useTheme() const navigation = useNavigation() - const {status} = useEvent(player, 'statusChange', {status: player.status}) - const doubleTapRef = useRef | null>(null) - const [queueLike] = usePostLikeMutationQueue(post, 'ImmersiveVideo') + // const {status} = useEvent(player, 'statusChange', {status: player.status}) const seekingAnimationSV = useSharedValue(0) const pushToProfile = useNonReactiveCallback(() => { navigation.navigate('Profile', {name: post.author.did}) }) - const togglePlayPause = () => { - doubleTapRef.current = null - if (player.playing) { - player.pause() - } else { - player.play() - } - } - - const onPress = () => { - if (doubleTapRef.current) { - clearTimeout(doubleTapRef.current) - doubleTapRef.current = null - queueLike() - } else { - doubleTapRef.current = setTimeout(togglePlayPause, 200) - } - } - const gesture = useMemo(() => { const dragLeftGesture = Gesture.Pan() .simultaneousWithExternalGesture(scrollGesture) @@ -552,49 +490,40 @@ function Overlay({ <> - - - - - - - - {sanitizeDisplayName( - post.author.displayName || post.author.handle, - )} - - - {sanitizeHandle(post.author.handle, '@')} - - + + + + + + + + + + + + {sanitizeDisplayName( + post.author.displayName || post.author.handle, + )} + + + {sanitizeHandle(post.author.handle, '@')} + - {record?.text?.trim() && ( + + {record?.text?.trim() && ( + - )} - {record && ( + + )} + {record && ( + - )} - + + )} - - {player && active ? ( - - ) : ( - - )} + + {player && active ? ( + + ) : ( + + )} + + {/* {isAndroid && status === 'loading' && ( )} + */} ) } -function ExpandableRichTextView({ - value, - authorHandle, -}: { - value: RichTextAPI - authorHandle?: string -}) { - const {height: screenHeight} = useWindowDimensions() - const [expanded, setExpanded] = useState(false) - const [constrained, setConstrained] = useState(false) - const [contentHeight, setContentHeight] = useState(0) - const {_} = useLingui() - - return ( - { - if (expanded) { - LayoutAnimation.configureNext({ - duration: 500, - update: {type: 'spring', springDamping: 0.6}, - }) - } - setContentHeight(h) - }} - style={{height: Math.min(contentHeight, screenHeight * 0.5)}} - contentContainerStyle={[ - a.gap_xs, - expanded ? [a.align_start] : a.flex_row, - ]}> - { - if (!constrained && evt.nativeEvent.lines.length > 1) { - setConstrained(true) - } - }} - /> - {constrained && ( - - )} - - ) +/** + * Magic number that matches the Scrubber height + */ +function ScrubberPlaceholder() { + return } function Scrubber({ @@ -814,7 +691,7 @@ function Scrubber({ { left: 0, right: 0, - bottom: tokens.space.xl + tokens.space._4xl + insets.bottom, + bottom: insets.bottom + 48, }, timeStyle, ]} @@ -834,15 +711,18 @@ function Scrubber({ + { + if (expanded) { + LayoutAnimation.configureNext({ + duration: 500, + update: {type: 'spring', springDamping: 0.6}, + }) + } + setContentHeight(h) + }} + style={{height: Math.min(contentHeight, screenHeight * 0.5)}} + contentContainerStyle={[ + a.gap_xs, + expanded ? [a.align_start] : a.flex_row, + ]}> + { + if (!constrained && evt.nativeEvent.lines.length > 1) { + setConstrained(true) + } + }} + /> + {constrained && ( + + )} + + ) +} + +function VideoItemPlaceholder({ + embed, + style, +}: { + embed: AppBskyEmbedVideo.View + style?: ImageStyle +}) { + const src = embed.thumbnail + return src ? ( + + ) : null +} + +function PlayPauseTapArea({ + player, + post, +}: { + player?: VideoPlayer + post: Shadow +}) { + const doubleTapRef = useRef | null>(null) + const [queueLike] = usePostLikeMutationQueue(post, 'ImmersiveVideo') + const togglePlayPause = () => { + if (!player) return + doubleTapRef.current = null + if (player.playing) { + player.pause() + } else { + player.play() + } + } + + const onPress = () => { + if (doubleTapRef.current) { + clearTimeout(doubleTapRef.current) + doubleTapRef.current = null + queueLike() + } else { + doubleTapRef.current = setTimeout(togglePlayPause, 200) + } + } + + return ( + + ) +} + function clamp(num: number, min: number, max: number) { 'worklet' return Math.min(Math.max(num, min), max) } + +/* + * If the video is taller than 9:16 + */ +function isTallAspectRatio(aspectRatio: AppBskyEmbedVideo.View['aspectRatio']) { + const videoAspectRatio = + (aspectRatio?.width ?? 1) / (aspectRatio?.height ?? 1) + return videoAspectRatio <= 9 / 16 +}