clean up component structure and organisation
This commit is contained in:
@@ -32,9 +32,7 @@ export function VideoEmbed({source}: {source: string}) {
|
||||
active={active}
|
||||
setActive={setActive}
|
||||
// web only
|
||||
sendPosition={() => {}}
|
||||
onScreen={true}
|
||||
onGoFarOffScreen={() => {}}
|
||||
/>
|
||||
) : (
|
||||
<Button
|
||||
|
||||
@@ -45,8 +45,6 @@ export function VideoEmbed({source}: {source: string}) {
|
||||
[key],
|
||||
)
|
||||
|
||||
console.log(key)
|
||||
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
@@ -61,20 +59,84 @@ export function VideoEmbed({source}: {source: string}) {
|
||||
style={{display: 'flex', flex: 1, cursor: 'default'}}
|
||||
onClick={evt => evt.stopPropagation()}>
|
||||
<ErrorBoundary renderError={renderError} key={key}>
|
||||
<VideoEmbedInner
|
||||
source={source}
|
||||
active={active}
|
||||
setActive={setActive}
|
||||
<ViewportObserver
|
||||
sendPosition={sendPosition}
|
||||
onScreen={onScreen}
|
||||
isAnyViewActive={currentActiveView !== null}
|
||||
/>
|
||||
isAnyViewActive={currentActiveView !== null}>
|
||||
<VideoEmbedInner
|
||||
source={source}
|
||||
active={active}
|
||||
setActive={setActive}
|
||||
onScreen={onScreen}
|
||||
/>
|
||||
</ViewportObserver>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a 100vh tall div and watches it with an IntersectionObserver to
|
||||
* send the position of the div when it's near the screen.
|
||||
*/
|
||||
function ViewportObserver({
|
||||
children,
|
||||
sendPosition,
|
||||
isAnyViewActive,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
sendPosition: (position: number) => void
|
||||
isAnyViewActive?: boolean
|
||||
}) {
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
const [nearScreen, setNearScreen] = useState(false)
|
||||
|
||||
// Send position when scrolling. This is done with an IntersectionObserver
|
||||
// observing a div of 100vh height
|
||||
useEffect(() => {
|
||||
if (!ref.current) return
|
||||
const observer = new IntersectionObserver(
|
||||
entries => {
|
||||
const entry = entries[0]
|
||||
if (!entry) return
|
||||
const position =
|
||||
entry.boundingClientRect.y + entry.boundingClientRect.height / 2
|
||||
sendPosition(position)
|
||||
setNearScreen(entry.isIntersecting)
|
||||
},
|
||||
{threshold: Array.from({length: 101}, (_, i) => i / 100)},
|
||||
)
|
||||
observer.observe(ref.current)
|
||||
return () => observer.disconnect()
|
||||
}, [sendPosition])
|
||||
|
||||
// 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={{
|
||||
position: 'absolute',
|
||||
top: 'calc(50% - 50vh)',
|
||||
left: '50%',
|
||||
height: '100vh',
|
||||
width: 1,
|
||||
pointerEvents: 'none',
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
function VideoError({error, retry}: {error: unknown; retry: () => void}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
|
||||
@@ -17,9 +17,7 @@ export function VideoEmbedInner({}: {
|
||||
source: string
|
||||
active: boolean
|
||||
setActive: () => void
|
||||
sendPosition: (position: number) => void
|
||||
onScreen: boolean
|
||||
isAnyViewActive?: boolean
|
||||
}) {
|
||||
const player = useVideoPlayer()
|
||||
const aref = useAnimatedRef<Animated.View>()
|
||||
|
||||
@@ -6,68 +6,6 @@ import {atoms as a} from '#/alf'
|
||||
import {Controls} from './VideoWebControls'
|
||||
|
||||
export function VideoEmbedInner({
|
||||
active,
|
||||
sendPosition,
|
||||
isAnyViewActive,
|
||||
...props
|
||||
}: {
|
||||
source: string
|
||||
active: boolean
|
||||
setActive: () => void
|
||||
sendPosition: (position: number) => void
|
||||
onScreen: boolean
|
||||
isAnyViewActive?: boolean
|
||||
}) {
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
const [nearScreen, setNearScreen] = useState(false)
|
||||
|
||||
// Send position when scrolling. This is done with an IntersectionObserver
|
||||
// observing a div of 100vh height
|
||||
useEffect(() => {
|
||||
if (!ref.current) return
|
||||
const observer = new IntersectionObserver(
|
||||
entries => {
|
||||
const entry = entries[0]
|
||||
if (!entry) return
|
||||
const position =
|
||||
entry.boundingClientRect.y + entry.boundingClientRect.height / 2
|
||||
sendPosition(position)
|
||||
setNearScreen(entry.isIntersecting)
|
||||
},
|
||||
{threshold: Array.from({length: 101}, (_, i) => i / 100)},
|
||||
)
|
||||
observer.observe(ref.current)
|
||||
return () => observer.disconnect()
|
||||
}, [sendPosition])
|
||||
|
||||
// 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 && <VideoPlayer active={active} {...props} />}
|
||||
<div
|
||||
ref={ref}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 'calc(50% - 50vh)',
|
||||
left: '50%',
|
||||
height: '100vh',
|
||||
width: 1,
|
||||
pointerEvents: 'none',
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export function VideoPlayer({
|
||||
source,
|
||||
active,
|
||||
setActive,
|
||||
|
||||
Reference in New Issue
Block a user