|
1 |
| -import * as React from 'react' |
| 1 | +import React, { useCallback, useContext, useEffect, useRef, useState } from 'react' |
2 | 2 | import _ from 'underscore'
|
3 | 3 | import { RundownTiming } from './RundownTiming.js'
|
4 | 4 | import { RundownTimingContext } from '../../../lib/rundownTiming.js'
|
@@ -155,6 +155,66 @@ export function withTiming<IProps, IState>(
|
155 | 155 | }
|
156 | 156 | }
|
157 | 157 |
|
| 158 | +function getFilterFunction( |
| 159 | + filter: TimingFilterFunction | string | (string | number)[] | undefined |
| 160 | +): TimingFilterFunction | undefined { |
| 161 | + if (typeof filter === 'function') { |
| 162 | + return filter |
| 163 | + } else if (filter) { |
| 164 | + return _.property(filter as string) |
| 165 | + } |
| 166 | + return undefined |
| 167 | +} |
| 168 | + |
| 169 | +export function useTiming({ |
| 170 | + tickResolution, |
| 171 | + dataResolution, |
| 172 | + filter, |
| 173 | +}: { |
| 174 | + tickResolution: TimingTickResolution |
| 175 | + dataResolution: TimingDataResolution |
| 176 | + filter?: TimingFilterFunction | string | (string | number)[] |
| 177 | +}): RundownTimingContext { |
| 178 | + const [_0, setForceUpdate] = useState(0) |
| 179 | + |
| 180 | + const context = useContext(RundownTimingProviderContext) |
| 181 | + |
| 182 | + const highResDurations: RundownTimingContext = context.durations |
| 183 | + const syncedDurations: RundownTimingContext = context.syncedDurations |
| 184 | + |
| 185 | + const isDirty = useRef(false) |
| 186 | + const previousValue = useRef<RundownTimingContext | null>(null) |
| 187 | + |
| 188 | + const filterGetter = useRef(getFilterFunction(filter)) |
| 189 | + |
| 190 | + const refreshComponent = useCallback(() => { |
| 191 | + if (!filterGetter.current) { |
| 192 | + setForceUpdate(Date.now()) |
| 193 | + } else { |
| 194 | + const buf = filterGetter.current?.(context.durations || {}) |
| 195 | + if (isDirty.current || !_.isEqual(buf, previousValue.current)) { |
| 196 | + previousValue.current = buf |
| 197 | + isDirty.current = false |
| 198 | + setForceUpdate(Date.now()) |
| 199 | + } |
| 200 | + } |
| 201 | + }, [filter]) |
| 202 | + |
| 203 | + useEffect(() => { |
| 204 | + window.addEventListener(rundownTimingEventFromTickResolution(tickResolution), refreshComponent) |
| 205 | + |
| 206 | + return () => { |
| 207 | + window.removeEventListener(rundownTimingEventFromTickResolution(tickResolution), refreshComponent) |
| 208 | + } |
| 209 | + }, [tickResolution, refreshComponent]) |
| 210 | + |
| 211 | + if (componentIsDirty(filterGetter.current, highResDurations, dataResolution)) { |
| 212 | + isDirty.current = true |
| 213 | + } |
| 214 | + |
| 215 | + return rundownTimingDataFromDataResolution(dataResolution, highResDurations, syncedDurations) |
| 216 | +} |
| 217 | + |
158 | 218 | function componentIsDirty(
|
159 | 219 | filterGetter: ((...args: any[]) => any) | undefined,
|
160 | 220 | highResDurations: RundownTimingContext,
|
|
0 commit comments