clean up component structure and organisation
This commit is contained in:
@@ -32,9 +32,7 @@ export function VideoEmbed({source}: {source: string}) {
|
|||||||
active={active}
|
active={active}
|
||||||
setActive={setActive}
|
setActive={setActive}
|
||||||
// web only
|
// web only
|
||||||
sendPosition={() => {}}
|
|
||||||
onScreen={true}
|
onScreen={true}
|
||||||
onGoFarOffScreen={() => {}}
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -45,8 +45,6 @@ export function VideoEmbed({source}: {source: string}) {
|
|||||||
[key],
|
[key],
|
||||||
)
|
)
|
||||||
|
|
||||||
console.log(key)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
@@ -61,20 +59,84 @@ export function VideoEmbed({source}: {source: string}) {
|
|||||||
style={{display: 'flex', flex: 1, cursor: 'default'}}
|
style={{display: 'flex', flex: 1, cursor: 'default'}}
|
||||||
onClick={evt => evt.stopPropagation()}>
|
onClick={evt => evt.stopPropagation()}>
|
||||||
<ErrorBoundary renderError={renderError} key={key}>
|
<ErrorBoundary renderError={renderError} key={key}>
|
||||||
<VideoEmbedInner
|
<ViewportObserver
|
||||||
source={source}
|
|
||||||
active={active}
|
|
||||||
setActive={setActive}
|
|
||||||
sendPosition={sendPosition}
|
sendPosition={sendPosition}
|
||||||
onScreen={onScreen}
|
isAnyViewActive={currentActiveView !== null}>
|
||||||
isAnyViewActive={currentActiveView !== null}
|
<VideoEmbedInner
|
||||||
/>
|
source={source}
|
||||||
|
active={active}
|
||||||
|
setActive={setActive}
|
||||||
|
onScreen={onScreen}
|
||||||
|
/>
|
||||||
|
</ViewportObserver>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
</View>
|
</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}) {
|
function VideoError({error, retry}: {error: unknown; retry: () => void}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
|||||||
@@ -17,9 +17,7 @@ export function VideoEmbedInner({}: {
|
|||||||
source: string
|
source: string
|
||||||
active: boolean
|
active: boolean
|
||||||
setActive: () => void
|
setActive: () => void
|
||||||
sendPosition: (position: number) => void
|
|
||||||
onScreen: boolean
|
onScreen: boolean
|
||||||
isAnyViewActive?: boolean
|
|
||||||
}) {
|
}) {
|
||||||
const player = useVideoPlayer()
|
const player = useVideoPlayer()
|
||||||
const aref = useAnimatedRef<Animated.View>()
|
const aref = useAnimatedRef<Animated.View>()
|
||||||
|
|||||||
@@ -6,68 +6,6 @@ import {atoms as a} from '#/alf'
|
|||||||
import {Controls} from './VideoWebControls'
|
import {Controls} from './VideoWebControls'
|
||||||
|
|
||||||
export function VideoEmbedInner({
|
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,
|
source,
|
||||||
active,
|
active,
|
||||||
setActive,
|
setActive,
|
||||||
|
|||||||
Reference in New Issue
Block a user