Skip to content

Commit

Permalink
feat(Output): create a hook for handling scrolling
Browse files Browse the repository at this point in the history
  • Loading branch information
jstarpl committed Jan 25, 2024
1 parent 17b0fdb commit 1d563f4
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 27 deletions.
40 changes: 40 additions & 0 deletions packages/apps/client/src/hooks/useControllerMessages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useEffect, useRef } from 'react'
import { RootAppStore } from 'src/stores/RootAppStore'

export function useControllerMessages(ref: React.RefObject<HTMLElement>, heightPx: number, fontSizePx: number) {
const speed = useRef(0)
const position = useRef(0)
const lastRequest = useRef<number | null>(null)
const lastFrameTime = useRef<number | null>(null)

useEffect(() => {
const onMessage = (message: { speed: number }) => {
console.log('received message', message)

speed.current = message.speed
}

RootAppStore.connection.controller.on('message', onMessage)
RootAppStore.connection.controller.subscribeToMessages().catch(console.error)

const onFrame = (now: number) => {
const frameTime = lastFrameTime.current === null ? 16 : now - lastFrameTime.current
const scrollBy = ((speed.current * fontSizePx) / 300) * frameTime
position.current = Math.max(0, position.current + scrollBy)
console.log(position.current)

ref.current?.scrollTo(0, position.current)

lastFrameTime.current = now
lastRequest.current = window.requestAnimationFrame(onFrame)
}

lastRequest.current = window.requestAnimationFrame(onFrame)

return () => {
RootAppStore.connection.controller.off('message', onMessage)

if (lastRequest.current !== null) window.cancelAnimationFrame(lastRequest.current)
}
}, [ref, heightPx, fontSizePx])
}
39 changes: 15 additions & 24 deletions packages/apps/client/src/views/Output/Output.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useMemo, useRef } from 'react'
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { observer } from 'mobx-react-lite'
import { RootAppStore } from 'src/stores/RootAppStore.ts'

Expand All @@ -9,41 +9,38 @@ import { getCurrentTime } from 'src/lib/getCurrentTime'
import { useQueryParam } from 'src/lib/useQueryParam'

import classes from './Output.module.scss'
import { useControllerMessages } from 'src/hooks/useControllerMessages'

const Output = observer(function Output(): React.ReactElement {
const rootEl = useRef<HTMLDivElement>(null)
const speed = useRef(0)
const [size, setSize] = useState({ height: window.innerHeight, width: window.innerWidth })

const isPrimary = useQueryParam('primary') !== null

// On startup
useEffect(() => {
RootAppStore.outputSettingsStore.initialize() // load and subscribe
})

RootAppStore.connection.controller.on('message', (message) => {
console.log('received message', message)

speed.current = message.speed
})
RootAppStore.connection.controller.subscribeToMessages().catch(console.error)
const outputSettings = RootAppStore.outputSettingsStore.outputSettings

// don't do this, it's just for testing:
const interval = setInterval(() => {
rootEl.current?.scrollBy(0, speed.current)
}, 1000 / 60)
const fontSize = outputSettings.fontSize
const scaleVertical = outputSettings.mirrorVertically ? '-1' : '1'
const scaleHorizontal = outputSettings.mirrorHorizontally ? '-1' : '1'

return () => {
RootAppStore.connection.controller.off('message')
clearInterval(interval)
}
}, [])
useControllerMessages(rootEl, size.height, (fontSize * size.width) / 100)

const onViewPortSizeChanged = useCallback(() => {
const width = window.innerWidth
const height = window.innerHeight
const aspectRatio = width / height
setSize({ width, height })

if (!isPrimary) return

RootAppStore.connection.viewPort.update(null, {
_id: '',
aspectRatio: window.innerWidth / window.innerHeight,
aspectRatio,
// TODO: This should return the actual lastKnownState
lastKnownState: {
timestamp: getCurrentTime(),
Expand All @@ -65,8 +62,6 @@ const Output = observer(function Output(): React.ReactElement {
}
}, [onViewPortSizeChanged])

const outputSettings = RootAppStore.outputSettingsStore.outputSettings

const activeRundownPlaylistId = outputSettings?.activeRundownPlaylistId

useEffect(() => {
Expand Down Expand Up @@ -142,10 +137,6 @@ const Output = observer(function Output(): React.ReactElement {
*/

const fontSize = outputSettings.fontSize
const scaleVertical = outputSettings.mirrorVertically ? '-1' : '1'
const scaleHorizontal = outputSettings.mirrorHorizontally ? '-1' : '1'

const styleVariables = useMemo(
() =>
({
Expand Down
12 changes: 9 additions & 3 deletions packages/apps/client/src/views/RundownScript/PreviewPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { observer } from 'mobx-react-lite'
import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
import React, { useEffect, useMemo, useRef } from 'react'
import { RundownOutput } from 'src/components/RundownOutput/RundownOutput'
import { RootAppStore } from 'src/stores/RootAppStore'

import classes from './PreviewPanel.module.scss'
import { useSize } from 'src/lib/useSize'
import { useControllerMessages } from 'src/hooks/useControllerMessages'

export const PreviewPanel = observer(function PreviewPanel(): React.ReactNode {
const rootEl = useRef<HTMLDivElement>(null)
Expand All @@ -19,16 +20,21 @@ export const PreviewPanel = observer(function PreviewPanel(): React.ReactNode {

const viewPortAspectRatio = RootAppStore.viewportStore.viewPort.aspectRatio

const fontSize = outputSettings.fontSize

const size = useSize(rootEl)
const previewWidth = size?.width ?? 0
const previewHeight = size?.height ?? 0

useControllerMessages(rootEl, previewHeight, (previewWidth * fontSize) / 100)

const style = useMemo(
() =>
({
'--prompter-font-size-base': `${(previewWidth * outputSettings.fontSize) / 100}px`,
'--prompter-font-size-base': `${(previewWidth * fontSize) / 100}px`,
height: `${previewWidth / viewPortAspectRatio}px`,
} as React.CSSProperties),
[outputSettings.fontSize, previewWidth, viewPortAspectRatio]
[fontSize, previewWidth, viewPortAspectRatio]
)

return (
Expand Down

0 comments on commit 1d563f4

Please sign in to comment.