clean up component structure and organisation

This commit is contained in:
Samuel Newman
2024-08-02 22:40:09 +02:00
parent b2c2939742
commit ada19e1e7f
4 changed files with 71 additions and 75 deletions
@@ -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,