diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/dms/MessageContext.tsx | 17 | ||||
-rw-r--r-- | src/components/dms/MessageItemEmbed.tsx | 17 | ||||
-rw-r--r-- | src/view/com/util/post-embeds/VideoEmbed.tsx | 4 | ||||
-rw-r--r-- | src/view/com/util/post-embeds/VideoEmbed.web.tsx | 33 | ||||
-rw-r--r-- | src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx | 4 |
5 files changed, 50 insertions, 25 deletions
diff --git a/src/components/dms/MessageContext.tsx b/src/components/dms/MessageContext.tsx new file mode 100644 index 000000000..84056fb30 --- /dev/null +++ b/src/components/dms/MessageContext.tsx @@ -0,0 +1,17 @@ +import React from 'react' + +const MessageContext = React.createContext(false) + +export function MessageContextProvider({ + children, +}: { + children: React.ReactNode +}) { + return ( + <MessageContext.Provider value={true}>{children}</MessageContext.Provider> + ) +} + +export function useIsWithinMessage() { + return React.useContext(MessageContext) +} diff --git a/src/components/dms/MessageItemEmbed.tsx b/src/components/dms/MessageItemEmbed.tsx index 3db00aece..f9eb4d3af 100644 --- a/src/components/dms/MessageItemEmbed.tsx +++ b/src/components/dms/MessageItemEmbed.tsx @@ -4,6 +4,7 @@ import {AppBskyEmbedRecord} from '@atproto/api' import {PostEmbeds, PostEmbedViewContext} from '#/view/com/util/post-embeds' import {atoms as a, native, useTheme} from '#/alf' +import {MessageContextProvider} from './MessageContext' let MessageItemEmbed = ({ embed, @@ -13,13 +14,15 @@ let MessageItemEmbed = ({ const t = useTheme() return ( - <View style={[a.my_xs, t.atoms.bg, native({flexBasis: 0})]}> - <PostEmbeds - embed={embed} - allowNestedQuotes - viewContext={PostEmbedViewContext.Feed} - /> - </View> + <MessageContextProvider> + <View style={[a.my_xs, t.atoms.bg, native({flexBasis: 0})]}> + <PostEmbeds + embed={embed} + allowNestedQuotes + viewContext={PostEmbedViewContext.Feed} + /> + </View> + </MessageContextProvider> ) } MessageItemEmbed = React.memo(MessageItemEmbed) diff --git a/src/view/com/util/post-embeds/VideoEmbed.tsx b/src/view/com/util/post-embeds/VideoEmbed.tsx index 3175266e4..a672830db 100644 --- a/src/view/com/util/post-embeds/VideoEmbed.tsx +++ b/src/view/com/util/post-embeds/VideoEmbed.tsx @@ -11,6 +11,7 @@ import {useAutoplayDisabled} from 'state/preferences' import {VideoEmbedInnerNative} from '#/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerNative' import {atoms as a} from '#/alf' import {Button} from '#/components/Button' +import {useIsWithinMessage} from '#/components/dms/MessageContext' import {Loader} from '#/components/Loader' import {PlayButtonIcon} from '#/components/video/PlayButtonIcon' import {VisibilityView} from '../../../../../modules/expo-bluesky-swiss-army' @@ -68,7 +69,8 @@ function InnerWrapper({embed}: Props) { const [isMuted, setIsMuted] = useState(player.muted) const [isFullscreen, setIsFullscreen] = React.useState(false) const [timeRemaining, setTimeRemaining] = React.useState(0) - const disableAutoplay = useAutoplayDisabled() + const isWithinMessage = useIsWithinMessage() + const disableAutoplay = useAutoplayDisabled() || isWithinMessage const isActive = embed.playlist === activeSource && activeViewId === viewId // There are some different loading states that we should pay attention to and show a spinner for const isLoading = diff --git a/src/view/com/util/post-embeds/VideoEmbed.web.tsx b/src/view/com/util/post-embeds/VideoEmbed.web.tsx index 3b6125c43..a41bf2634 100644 --- a/src/view/com/util/post-embeds/VideoEmbed.web.tsx +++ b/src/view/com/util/post-embeds/VideoEmbed.web.tsx @@ -12,6 +12,7 @@ import { VideoNotFoundError, } from '#/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerWeb' import {atoms as a} from '#/alf' +import {useIsWithinMessage} from '#/components/dms/MessageContext' import {useFullscreen} from '#/components/hooks/useFullscreen' import {ErrorBoundary} from '../ErrorBoundary' import {useActiveVideoWeb} from './ActiveVideoWebContext' @@ -42,6 +43,16 @@ export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) { return () => observer.disconnect() }, [sendPosition, isFullscreen]) + // In case scrolling hasn't started yet, send up the position + const isAnyViewActive = currentActiveView !== null + useEffect(() => { + if (ref.current && !isAnyViewActive) { + const rect = ref.current.getBoundingClientRect() + const position = rect.y + rect.height / 2 + sendPosition(position) + } + }, [isAnyViewActive, sendPosition]) + const [key, setKey] = useState(0) const renderError = useCallback( (error: unknown) => ( @@ -73,9 +84,7 @@ export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) { style={{display: 'flex', flex: 1, cursor: 'default'}} onClick={evt => evt.stopPropagation()}> <ErrorBoundary renderError={renderError} key={key}> - <ViewportObserver - sendPosition={sendPosition} - isAnyViewActive={currentActiveView !== null}> + <ViewportObserver sendPosition={sendPosition}> <VideoEmbedInnerWeb embed={embed} active={active} @@ -96,15 +105,14 @@ export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) { function ViewportObserver({ children, sendPosition, - isAnyViewActive, }: { children: React.ReactNode sendPosition: (position: number) => void - isAnyViewActive?: boolean }) { const ref = useRef<HTMLDivElement>(null) const [nearScreen, setNearScreen] = useState(false) const [isFullscreen] = useFullscreen() + const isWithinMessage = useIsWithinMessage() // Send position when scrolling. This is done with an IntersectionObserver // observing a div of 100vh height @@ -126,25 +134,18 @@ function ViewportObserver({ return () => observer.disconnect() }, [sendPosition, isFullscreen]) - // In case scrolling hasn't started yet, send up the position - useEffect(() => { - if (ref.current && !isAnyViewActive) { - const rect = ref.current.getBoundingClientRect() - const position = rect.y + rect.height / 2 - sendPosition(position) - } - }, [isAnyViewActive, sendPosition]) - return ( <View style={[a.flex_1, a.flex_row]}> {nearScreen && children} <div ref={ref} style={{ + // Don't escape bounds when in a message + ...(isWithinMessage + ? {top: 0, height: '100%'} + : {top: 'calc(50% - 50vh)', height: '100vh'}), position: 'absolute', - top: 'calc(50% - 50vh)', left: '50%', - height: '100vh', width: 1, pointerEvents: 'none', }} diff --git a/src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx b/src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx index 138791e48..bb15db083 100644 --- a/src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx +++ b/src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx @@ -15,6 +15,7 @@ import { } from '#/state/preferences' import {atoms as a, useTheme, web} from '#/alf' import {Button} from '#/components/Button' +import {useIsWithinMessage} from '#/components/dms/MessageContext' import {useFullscreen} from '#/components/hooks/useFullscreen' import {useInteractionState} from '#/components/hooks/useInteractionState' import { @@ -113,7 +114,8 @@ export function Controls({ }, [active, pause, setFocused]) // autoplay/pause based on visibility - const autoplayDisabled = useAutoplayDisabled() + const isWithinMessage = useIsWithinMessage() + const autoplayDisabled = useAutoplayDisabled() || isWithinMessage useEffect(() => { if (active) { if (onScreen) { |