about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/dms/MessageContext.tsx17
-rw-r--r--src/components/dms/MessageItemEmbed.tsx17
-rw-r--r--src/view/com/util/post-embeds/VideoEmbed.tsx4
-rw-r--r--src/view/com/util/post-embeds/VideoEmbed.web.tsx33
-rw-r--r--src/view/com/util/post-embeds/VideoEmbedInner/VideoWebControls.tsx4
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) {