mirror of
https://github.com/cpvalente/ontime.git
synced 2026-09-09 08:19:15 +00:00
refactor: improve performance in rundown
- leverage compiler - correct subscriptions from zustand
This commit is contained in:
committed by
Carlos Valente
parent
0de55e74a8
commit
8e32314667
@@ -33,7 +33,7 @@ export default function useRundown() {
|
|||||||
|
|
||||||
export function useRundownWithMetadata() {
|
export function useRundownWithMetadata() {
|
||||||
const { data, status } = useRundown();
|
const { data, status } = useRundown();
|
||||||
const { selectedEventId } = useSelectedEventId();
|
const selectedEventId = useSelectedEventId();
|
||||||
const rundownMetadata = useMemo(() => getRundownMetadata(data, selectedEventId), [data, selectedEventId]);
|
const rundownMetadata = useMemo(() => getRundownMetadata(data, selectedEventId), [data, selectedEventId]);
|
||||||
return { data, status, rundownMetadata };
|
return { data, status, rundownMetadata };
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,7 @@ export function useFlatRundown() {
|
|||||||
|
|
||||||
export function useFlatRundownWithMetadata() {
|
export function useFlatRundownWithMetadata() {
|
||||||
const { data, status } = useRundown();
|
const { data, status } = useRundown();
|
||||||
const { selectedEventId } = useSelectedEventId();
|
const selectedEventId = useSelectedEventId();
|
||||||
|
|
||||||
const rundownWithMetadata = useMemo(() => getFlatRundownMetadata(data, selectedEventId), [data, selectedEventId]);
|
const rundownWithMetadata = useMemo(() => getFlatRundownMetadata(data, selectedEventId), [data, selectedEventId]);
|
||||||
return { data: rundownWithMetadata, status };
|
return { data: rundownWithMetadata, status };
|
||||||
|
|||||||
@@ -128,13 +128,9 @@ export const setAuxTimer = {
|
|||||||
setDuration: (index: number, time: number) => sendSocket('auxtimer', { [index]: { duration: time } }),
|
setDuration: (index: number, time: number) => sendSocket('auxtimer', { [index]: { duration: time } }),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useSelectedEventId = createSelector((state: RuntimeStore) => ({
|
export const useSelectedEventId = createSelector((state: RuntimeStore) => state.eventNow?.id ?? null);
|
||||||
selectedEventId: state.eventNow?.id ?? null,
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const useCurrentGroupId = createSelector((state: RuntimeStore) => ({
|
export const useCurrentGroupId = createSelector((state: RuntimeStore) => state.groupNow?.id ?? null);
|
||||||
currentGroupId: state.groupNow?.id ?? null,
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const setEventPlayback = {
|
export const setEventPlayback = {
|
||||||
loadEvent: (id: string) => sendSocket('load', { id }),
|
loadEvent: (id: string) => sendSocket('load', { id }),
|
||||||
@@ -147,9 +143,7 @@ export const useTimer = createSelector((state: RuntimeStore) => ({
|
|||||||
...state.timer,
|
...state.timer,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useClock = createSelector((state: RuntimeStore) => ({
|
export const useClock = createSelector((state: RuntimeStore) => state.clock);
|
||||||
clock: state.clock,
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const useNextFlag = createSelector((state: RuntimeStore) => ({
|
export const useNextFlag = createSelector((state: RuntimeStore) => ({
|
||||||
id: state.eventFlag?.id ?? null,
|
id: state.eventFlag?.id ?? null,
|
||||||
@@ -173,28 +167,16 @@ export const useExpectedStartData = createSelector((state: RuntimeStore) => ({
|
|||||||
clock: state.clock,
|
clock: state.clock,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const usePing = createSelector((state: RuntimeStore) => ({
|
export const usePing = createSelector((state: RuntimeStore) => state.ping);
|
||||||
ping: state.ping,
|
|
||||||
}));
|
|
||||||
|
|
||||||
/** convert ping into a derived value which changes less often */
|
/** convert ping into a derived value which changes less often */
|
||||||
export const useIsOnline = createSelector((state: RuntimeStore) => ({
|
export const useIsOnline = createSelector((state: RuntimeStore) => state.ping > 0);
|
||||||
isOnline: state.ping > 0,
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const useOffsetMode = createSelector((state: RuntimeStore) => ({
|
export const useOffsetMode = createSelector((state: RuntimeStore) => state.offset.mode);
|
||||||
offsetMode: state.offset.mode,
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const setOffsetMode = (payload: OffsetMode) => sendSocket('offsetmode', payload);
|
export const setOffsetMode = (payload: OffsetMode) => sendSocket('offsetmode', payload);
|
||||||
|
|
||||||
export const usePlayback = () => {
|
export const usePlayback = createSelector((state: RuntimeStore) => state.timer.playback);
|
||||||
const featureSelector = (state: RuntimeStore) => ({
|
|
||||||
playback: state.timer.playback,
|
|
||||||
});
|
|
||||||
|
|
||||||
return useRuntimeStore(featureSelector);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ======================= Overview data subscriptions ======================= */
|
/* ======================= Overview data subscriptions ======================= */
|
||||||
|
|
||||||
@@ -204,9 +186,7 @@ export const useStartTimesOverview = createSelector((state: RuntimeStore) => ({
|
|||||||
plannedEnd: state.rundown.plannedEnd,
|
plannedEnd: state.rundown.plannedEnd,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useRundownExpectedEnd = createSelector((state: RuntimeStore) => ({
|
export const useRundownExpectedEnd = createSelector((state: RuntimeStore) => state.offset.expectedRundownEnd);
|
||||||
expectedEnd: state.offset.expectedRundownEnd,
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const useProgressOverview = createSelector((state: RuntimeStore) => ({
|
export const useProgressOverview = createSelector((state: RuntimeStore) => ({
|
||||||
numEvents: state.rundown.numEvents,
|
numEvents: state.rundown.numEvents,
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export default function NetworkLogPanel({ location }: PanelBaseProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function OntimeCloudStats() {
|
function OntimeCloudStats() {
|
||||||
const { ping } = usePing();
|
const ping = usePing();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send immediate ping request, and keep sending on an interval
|
* Send immediate ping request, and keep sending on an interval
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export default function OperatorLoader() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Operator({ rundown, rundownMetadata, customFields, settings }: OperatorData) {
|
function Operator({ rundown, rundownMetadata, customFields, settings }: OperatorData) {
|
||||||
const { selectedEventId } = useSelectedEventId();
|
const selectedEventId = useSelectedEventId();
|
||||||
const { subscribe, mainSource, secondarySource, shouldEdit, hidePast, showStart } = useOperatorOptions();
|
const { subscribe, mainSource, secondarySource, shouldEdit, hidePast, showStart } = useOperatorOptions();
|
||||||
|
|
||||||
const [showEditPrompt, setShowEditPrompt] = useState(false);
|
const [showEditPrompt, setShowEditPrompt] = useState(false);
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ interface OverviewWrapperProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function OverviewWrapper({ navElements, children }: PropsWithChildren<OverviewWrapperProps>) {
|
export function OverviewWrapper({ navElements, children }: PropsWithChildren<OverviewWrapperProps>) {
|
||||||
const { isOnline } = useIsOnline();
|
const isOnline = useIsOnline();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cx([style.overview, !isOnline && style.isOffline])}>
|
<div className={cx([style.overview, !isOnline && style.isOffline])}>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ export function StartTimes({ shouldFormat }: OverviewTimeElementsProps) {
|
|||||||
* Extracted to improve performance as this is a ticking value
|
* Extracted to improve performance as this is a ticking value
|
||||||
*/
|
*/
|
||||||
function RundownExpectedEnd({ shouldFormat }: OverviewTimeElementsProps) {
|
function RundownExpectedEnd({ shouldFormat }: OverviewTimeElementsProps) {
|
||||||
const { expectedEnd } = useRundownExpectedEnd();
|
const expectedEnd = useRundownExpectedEnd();
|
||||||
|
|
||||||
const [maybeExpectedEnd, maybeExpectedDaySpan] = useMemo(() => calculateEndAndDaySpan(expectedEnd), [expectedEnd]);
|
const [maybeExpectedEnd, maybeExpectedDaySpan] = useMemo(() => calculateEndAndDaySpan(expectedEnd), [expectedEnd]);
|
||||||
const maybeExpectedEndText = (() => {
|
const maybeExpectedEndText = (() => {
|
||||||
@@ -169,7 +169,7 @@ export function MetadataTimes() {
|
|||||||
|
|
||||||
function GroupTimes() {
|
function GroupTimes() {
|
||||||
const { clock, mode, groupExpectedEnd, actualGroupStart, currentDay, playback } = useGroupTimerOverView();
|
const { clock, mode, groupExpectedEnd, actualGroupStart, currentDay, playback } = useGroupTimerOverView();
|
||||||
const { currentGroupId } = useCurrentGroupId();
|
const currentGroupId = useCurrentGroupId();
|
||||||
const group = useEntry(currentGroupId) as OntimeGroup | null;
|
const group = useEntry(currentGroupId) as OntimeGroup | null;
|
||||||
|
|
||||||
const active = isPlaybackActive(playback);
|
const active = isPlaybackActive(playback);
|
||||||
@@ -298,7 +298,7 @@ export function OffsetOverview() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function ClockOverview({ shouldFormat, className }: OverviewTimeElementsProps & { className?: string }) {
|
export function ClockOverview({ shouldFormat, className }: OverviewTimeElementsProps & { className?: string }) {
|
||||||
const { clock } = useClock();
|
const clock = useClock();
|
||||||
const formattedClock = shouldFormat ? formatTime(clock) : millisToString(clock);
|
const formattedClock = shouldFormat ? formatTime(clock) : millisToString(clock);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ export default function RundownEntry({
|
|||||||
totalGap,
|
totalGap,
|
||||||
isLinkedToLoaded,
|
isLinkedToLoaded,
|
||||||
}: RundownEntryProps) {
|
}: RundownEntryProps) {
|
||||||
|
'use memo';
|
||||||
|
|
||||||
if (isOntimeEvent(data)) {
|
if (isOntimeEvent(data)) {
|
||||||
return (
|
return (
|
||||||
<RundownEvent
|
<RundownEvent
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useMemo } from 'react';
|
||||||
import {
|
import {
|
||||||
isOntimeDelay,
|
isOntimeDelay,
|
||||||
isOntimeEvent,
|
isOntimeEvent,
|
||||||
@@ -24,27 +24,22 @@ export default function RundownEntryEditor() {
|
|||||||
const selectedEvents = useEventSelection((state) => state.selectedEvents);
|
const selectedEvents = useEventSelection((state) => state.selectedEvents);
|
||||||
const { data } = useRundown();
|
const { data } = useRundown();
|
||||||
|
|
||||||
const [entry, setEntry] = useState<OntimeEvent | OntimeGroup | OntimeMilestone | null>(null);
|
const entry = useMemo<OntimeEvent | OntimeGroup | OntimeMilestone | null>(() => {
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (data.order.length === 0) {
|
if (data.order.length === 0) {
|
||||||
setEntry(null);
|
return null;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedEventId = Array.from(selectedEvents).at(0);
|
const selectedEventId = Array.from(selectedEvents).at(0);
|
||||||
if (!selectedEventId) {
|
if (!selectedEventId) {
|
||||||
setEntry(null);
|
return null;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const event = data.entries[selectedEventId];
|
const event = data.entries[selectedEventId];
|
||||||
|
|
||||||
if (event && !isOntimeDelay(event)) {
|
if (event && !isOntimeDelay(event)) {
|
||||||
setEntry(event);
|
return event;
|
||||||
} else {
|
|
||||||
setEntry(null);
|
|
||||||
}
|
}
|
||||||
}, [data.order, data.entries, selectedEvents]);
|
return null;
|
||||||
|
}, [data.order.length, data.entries, selectedEvents]);
|
||||||
|
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
return <EventEditorEmpty />;
|
return <EventEditorEmpty />;
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ interface RundownDelayProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function RundownDelay({ data, hasCursor }: RundownDelayProps) {
|
export default function RundownDelay({ data, hasCursor }: RundownDelayProps) {
|
||||||
|
'use memo';
|
||||||
|
|
||||||
const { applyDelay, deleteEntry } = useEntryActions();
|
const { applyDelay, deleteEntry } = useEntryActions();
|
||||||
const handleRef = useRef<null | HTMLSpanElement>(null);
|
const handleRef = useRef<null | HTMLSpanElement>(null);
|
||||||
|
|
||||||
|
|||||||
@@ -91,10 +91,21 @@ export default function RundownEvent({
|
|||||||
isLinkedToLoaded,
|
isLinkedToLoaded,
|
||||||
hasTriggers,
|
hasTriggers,
|
||||||
}: RundownEventProps) {
|
}: RundownEventProps) {
|
||||||
const { selectedEventId, setSelectedEventId, clearSelectedEventId } = useEventIdSwapping();
|
'use memo';
|
||||||
|
|
||||||
|
const selectedEventId = useEventIdSwapping((state) => state.selectedEventId);
|
||||||
|
const setSelectedEventId = useEventIdSwapping((state) => state.setSelectedEventId);
|
||||||
|
const clearSelectedEventId = useEventIdSwapping((state) => state.clearSelectedEventId);
|
||||||
|
|
||||||
const { updateEntry, batchUpdateEvents, clone, deleteEntry, groupEntries, swapEvents } = useEntryActions();
|
const { updateEntry, batchUpdateEvents, clone, deleteEntry, groupEntries, swapEvents } = useEntryActions();
|
||||||
|
|
||||||
const { selectedEvents, unselect, setSelectedEvents, clearSelectedEvents } = useEventSelection();
|
const isSelected = useEventSelection((state) => state.selectedEvents.has(eventId));
|
||||||
|
const unselect = useEventSelection((state) => state.unselect);
|
||||||
|
const setSelectedEvents = useEventSelection((state) => state.setSelectedEvents);
|
||||||
|
const clearSelectedEvents = useEventSelection((state) => state.clearSelectedEvents);
|
||||||
|
|
||||||
|
const selectedEvents = useEventSelection((state) => state.selectedEvents);
|
||||||
|
|
||||||
const handleRef = useRef<null | HTMLSpanElement>(null);
|
const handleRef = useRef<null | HTMLSpanElement>(null);
|
||||||
const [isVisible, setIsVisible] = useState(false);
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
|
|
||||||
@@ -250,7 +261,6 @@ export default function RundownEvent({
|
|||||||
};
|
};
|
||||||
}, [handleRef]);
|
}, [handleRef]);
|
||||||
|
|
||||||
const isSelected = selectedEvents.has(eventId);
|
|
||||||
const blockClasses = cx([
|
const blockClasses = cx([
|
||||||
style.rundownEvent,
|
style.rundownEvent,
|
||||||
skip ? style.skip : null,
|
skip ? style.skip : null,
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export default function RundownEventChip({
|
|||||||
duration,
|
duration,
|
||||||
isLinkedToLoaded,
|
isLinkedToLoaded,
|
||||||
}: RundownEventChipProps) {
|
}: RundownEventChipProps) {
|
||||||
const { playback } = usePlayback();
|
const playback = usePlayback();
|
||||||
|
|
||||||
if (isLoaded) {
|
if (isLoaded) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -33,9 +33,13 @@ interface RundownGroupProps {
|
|||||||
|
|
||||||
//TODO: the group should maybe include a multiple day indicator
|
//TODO: the group should maybe include a multiple day indicator
|
||||||
export default function RundownGroup({ data, hasCursor, collapsed, onCollapse }: RundownGroupProps) {
|
export default function RundownGroup({ data, hasCursor, collapsed, onCollapse }: RundownGroupProps) {
|
||||||
|
'use memo';
|
||||||
|
|
||||||
const handleRef = useRef<null | HTMLSpanElement>(null);
|
const handleRef = useRef<null | HTMLSpanElement>(null);
|
||||||
const { clone, ungroup, deleteEntry } = useEntryActions();
|
const { clone, ungroup, deleteEntry } = useEntryActions();
|
||||||
const { selectedEvents, setSingleEntrySelection } = useEventSelection();
|
|
||||||
|
const setSingleEntrySelection = useEventSelection((state) => state.setSingleEntrySelection);
|
||||||
|
const selectedEvents = useEventSelection((state) => state.selectedEvents);
|
||||||
|
|
||||||
const [onContextMenu] = useContextMenu<HTMLDivElement>([
|
const [onContextMenu] = useContextMenu<HTMLDivElement>([
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export default memo(RundownHeader);
|
|||||||
function RundownHeader({ viewMode, setViewMode }: RundownHeaderProps) {
|
function RundownHeader({ viewMode, setViewMode }: RundownHeaderProps) {
|
||||||
const [editorMode, setEditorMode] = useSessionStorage({ key: sessionKeys.editorMode, defaultValue: AppMode.Edit });
|
const [editorMode, setEditorMode] = useSessionStorage({ key: sessionKeys.editorMode, defaultValue: AppMode.Edit });
|
||||||
|
|
||||||
const { offsetMode } = useOffsetMode();
|
const offsetMode = useOffsetMode();
|
||||||
|
|
||||||
const toggleAppMode = (mode: AppMode[]) => {
|
const toggleAppMode = (mode: AppMode[]) => {
|
||||||
// we need to stop user from deselecting a mode
|
// we need to stop user from deselecting a mode
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ function RundownHeader() {
|
|||||||
defaultValue: AppMode.Edit,
|
defaultValue: AppMode.Edit,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { offsetMode } = useOffsetMode();
|
const offsetMode = useOffsetMode();
|
||||||
|
|
||||||
const toggleAppMode = (mode: AppMode[]) => {
|
const toggleAppMode = (mode: AppMode[]) => {
|
||||||
// we need to stop user from deselecting a mode
|
// we need to stop user from deselecting a mode
|
||||||
|
|||||||
@@ -22,9 +22,13 @@ interface RundownMilestoneProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function RundownMilestone({ colour, cue, entryId, hasCursor, title }: RundownMilestoneProps) {
|
export default function RundownMilestone({ colour, cue, entryId, hasCursor, title }: RundownMilestoneProps) {
|
||||||
|
'use memo';
|
||||||
|
|
||||||
const handleRef = useRef<null | HTMLSpanElement>(null);
|
const handleRef = useRef<null | HTMLSpanElement>(null);
|
||||||
const { updateEntry, deleteEntry } = useEntryActions();
|
const { updateEntry, deleteEntry } = useEntryActions();
|
||||||
const { selectedEvents, setSingleEntrySelection } = useEventSelection();
|
|
||||||
|
const selectedEvents = useEventSelection((state) => state.selectedEvents);
|
||||||
|
const setSingleEntrySelection = useEventSelection((state) => state.setSingleEntrySelection);
|
||||||
|
|
||||||
const [onContextMenu] = useContextMenu<HTMLDivElement>([
|
const [onContextMenu] = useContextMenu<HTMLDivElement>([
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ function ExtraInfo({ projectData, size, source }: ExtraInfoProps) {
|
|||||||
|
|
||||||
function BackstageClock() {
|
function BackstageClock() {
|
||||||
const { getLocalizedString } = useTranslation();
|
const { getLocalizedString } = useTranslation();
|
||||||
const { clock } = useClock();
|
const clock = useClock();
|
||||||
|
|
||||||
// gather timer data
|
// gather timer data
|
||||||
const formattedClock = formatTime(clock);
|
const formattedClock = formatTime(clock);
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ function CountdownContents({ playableEvents, subscriptions, goToEditMode }: Coun
|
|||||||
|
|
||||||
function CountdownClock() {
|
function CountdownClock() {
|
||||||
const { getLocalizedString } = useTranslation();
|
const { getLocalizedString } = useTranslation();
|
||||||
const { clock } = useClock();
|
const clock = useClock();
|
||||||
|
|
||||||
// gather timer data
|
// gather timer data
|
||||||
const formattedClock = formatTime(clock);
|
const formattedClock = formatTime(clock);
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ interface CountdownSubscriptionsProps {
|
|||||||
|
|
||||||
export default function CountdownSubscriptions({ subscribedEvents, goToEditMode }: CountdownSubscriptionsProps) {
|
export default function CountdownSubscriptions({ subscribedEvents, goToEditMode }: CountdownSubscriptionsProps) {
|
||||||
const { mainSource, secondarySource, showExpected } = useCountdownOptions();
|
const { mainSource, secondarySource, showExpected } = useCountdownOptions();
|
||||||
const { playback } = usePlayback();
|
const playback = usePlayback();
|
||||||
const { selectedEventId } = useSelectedEventId();
|
const selectedEventId = useSelectedEventId();
|
||||||
const showFab = useFadeOutOnInactivity(true);
|
const showFab = useFadeOutOnInactivity(true);
|
||||||
|
|
||||||
const { data: reportData } = useReport();
|
const { data: reportData } = useReport();
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export default function CuesheetTable({ columns, cuesheetMode, tableRoot = 'cues
|
|||||||
const hideTableSeconds = useOptions((state) => state.hideTableSeconds);
|
const hideTableSeconds = useOptions((state) => state.hideTableSeconds);
|
||||||
const hideIndexColumn = useOptions((state) => state.hideIndexColumn);
|
const hideIndexColumn = useOptions((state) => state.hideIndexColumn);
|
||||||
|
|
||||||
const { selectedEventId } = useSelectedEventId();
|
const selectedEventId = useSelectedEventId();
|
||||||
|
|
||||||
const virtuosoRef = useRef<TableVirtuosoHandle | null>(null);
|
const virtuosoRef = useRef<TableVirtuosoHandle | null>(null);
|
||||||
const { listeners } = useTableNav();
|
const { listeners } = useTableNav();
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export default function TimelinePageLoader() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function TimelinePage({ events, customFields, projectData, settings }: TimelineData) {
|
function TimelinePage({ events, customFields, projectData, settings }: TimelineData) {
|
||||||
const { selectedEventId } = useSelectedEventId();
|
const selectedEventId = useSelectedEventId();
|
||||||
const { mainSource } = useTimelineOptions();
|
const { mainSource } = useTimelineOptions();
|
||||||
// holds copy of the rundown with only relevant events
|
// holds copy of the rundown with only relevant events
|
||||||
const { scopedRundown, firstStart, totalDuration } = useScopedRundown(events, selectedEventId);
|
const { scopedRundown, firstStart, totalDuration } = useScopedRundown(events, selectedEventId);
|
||||||
@@ -73,7 +73,7 @@ function TimelinePage({ events, customFields, projectData, settings }: TimelineD
|
|||||||
|
|
||||||
function TimelineClock() {
|
function TimelineClock() {
|
||||||
const { getLocalizedString } = useTranslation();
|
const { getLocalizedString } = useTranslation();
|
||||||
const { clock } = useClock();
|
const clock = useClock();
|
||||||
|
|
||||||
// gather timer data
|
// gather timer data
|
||||||
const formattedClock = formatTime(clock);
|
const formattedClock = formatTime(clock);
|
||||||
|
|||||||
Reference in New Issue
Block a user