From ba6227695107de2386313156285a3897223d169a Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Thu, 6 Apr 2023 14:42:34 +0200 Subject: [PATCH] refactor: improve performance on EventBlock --- .../components/buttons/TooltipActionBtn.tsx | 8 +- .../rundown/event-block/EventBlockInner.tsx | 47 +---------- .../composite/EventBlockPlayback.tsx | 79 +++++++++++++++++++ .../composite/EventBlockTimers.tsx | 53 +++++++++---- .../rundown/quick-add-block/QuickAddBlock.tsx | 8 +- 5 files changed, 126 insertions(+), 69 deletions(-) create mode 100644 apps/client/src/features/rundown/event-block/composite/EventBlockPlayback.tsx diff --git a/apps/client/src/common/components/buttons/TooltipActionBtn.tsx b/apps/client/src/common/components/buttons/TooltipActionBtn.tsx index 3fff1c293..4d0c666b6 100644 --- a/apps/client/src/common/components/buttons/TooltipActionBtn.tsx +++ b/apps/client/src/common/components/buttons/TooltipActionBtn.tsx @@ -10,13 +10,7 @@ export default function TooltipActionBtn(props: TooltipActionBtnProps) { const { clickHandler, icon, size = 'xs', tooltip, openDelay = 0, className, ...rest } = props; return ( - + ); } diff --git a/apps/client/src/features/rundown/event-block/EventBlockInner.tsx b/apps/client/src/features/rundown/event-block/EventBlockInner.tsx index a88d40e3d..d3455acaa 100644 --- a/apps/client/src/features/rundown/event-block/EventBlockInner.tsx +++ b/apps/client/src/features/rundown/event-block/EventBlockInner.tsx @@ -4,26 +4,21 @@ import { IoCaretDownCircle } from '@react-icons/all-files/io5/IoCaretDownCircle' import { IoCaretUpCircle } from '@react-icons/all-files/io5/IoCaretUpCircle'; import { IoOptions } from '@react-icons/all-files/io5/IoOptions'; import { IoPeople } from '@react-icons/all-files/io5/IoPeople'; -import { IoPlay } from '@react-icons/all-files/io5/IoPlay'; import { IoPlayCircle } from '@react-icons/all-files/io5/IoPlayCircle'; import { IoPlayForwardCircle } from '@react-icons/all-files/io5/IoPlayForwardCircle'; -import { IoPlayOutline } from '@react-icons/all-files/io5/IoPlayOutline'; import { IoPlaySkipForwardCircle } from '@react-icons/all-files/io5/IoPlaySkipForwardCircle'; -import { IoReload } from '@react-icons/all-files/io5/IoReload'; -import { IoRemoveCircle } from '@react-icons/all-files/io5/IoRemoveCircle'; -import { IoRemoveCircleOutline } from '@react-icons/all-files/io5/IoRemoveCircleOutline'; import { IoStopCircle } from '@react-icons/all-files/io5/IoStopCircle'; import { IoTime } from '@react-icons/all-files/io5/IoTime'; import { EndAction, Playback, TimerType } from 'ontime-types'; import TooltipActionBtn from '../../../common/components/buttons/TooltipActionBtn'; -import { setEventPlayback } from '../../../common/hooks/useSocket'; import { useEventEditorStore } from '../../../common/stores/eventEditor'; import { tooltipDelayMid } from '../../../ontimeConfig'; import EditableBlockTitle from '../common/EditableBlockTitle'; import { EventItemActions } from '../RundownEntry'; import BlockActionMenu from './composite/BlockActionMenu'; +import EventBlockPlayback from './composite/EventBlockPlayback'; import EventBlockProgressBar from './composite/EventBlockProgressBar'; import EventBlockTimers from './composite/EventBlockTimers'; @@ -104,49 +99,13 @@ const EventBlockInner = (props: EventBlockInnerProps) => { return !renderInner ? null : ( <> -
- : } - {...tooltipProps} - {...blockBtnStyle} - clickHandler={() => actionHandler('update', { field: 'skip', value: !skip })} - tabIndex={-1} - disabled={selected} - /> - } - disabled={skip} - {...tooltipProps} - {...blockBtnStyle} - clickHandler={() => setEventPlayback.loadEvent(eventId)} - tabIndex={-1} - /> - : } - disabled={skip} - {...tooltipProps} - {...blockBtnStyle} - clickHandler={() => setEventPlayback.startEvent(eventId)} - backgroundColor={eventIsPlaying ? '#58A151' : undefined} - _hover={{ backgroundColor: eventIsPlaying ? '#58A151' : undefined }} - tabIndex={-1} - /> -
+ diff --git a/apps/client/src/features/rundown/event-block/composite/EventBlockPlayback.tsx b/apps/client/src/features/rundown/event-block/composite/EventBlockPlayback.tsx new file mode 100644 index 000000000..8d180e75f --- /dev/null +++ b/apps/client/src/features/rundown/event-block/composite/EventBlockPlayback.tsx @@ -0,0 +1,79 @@ +import { memo } from 'react'; +import { IoPlay } from '@react-icons/all-files/io5/IoPlay'; +import { IoPlayOutline } from '@react-icons/all-files/io5/IoPlayOutline'; +import { IoReload } from '@react-icons/all-files/io5/IoReload'; +import { IoRemoveCircle } from '@react-icons/all-files/io5/IoRemoveCircle'; +import { IoRemoveCircleOutline } from '@react-icons/all-files/io5/IoRemoveCircleOutline'; + +import TooltipActionBtn from '../../../../common/components/buttons/TooltipActionBtn'; +import { useEventAction } from '../../../../common/hooks/useEventAction'; +import { setEventPlayback } from '../../../../common/hooks/useSocket'; +import { tooltipDelayMid } from '../../../../ontimeConfig'; + +import style from '../EventBlock.module.scss'; + +const blockBtnStyle = { + size: 'sm', +}; + +const tooltipProps = { + openDelay: tooltipDelayMid, +}; + +interface EventBlockPlaybackProps { + eventId: string; + skip: boolean; + isPlaying: boolean; + selected: boolean; +} + +const EventBlockPlayback = (props: EventBlockPlaybackProps) => { + const { eventId, skip, isPlaying, selected } = props; + const { updateEvent } = useEventAction(); + + const toggleSkip = () => { + updateEvent({ id: eventId, skip: !skip }); + }; + + return ( +
+ : } + {...tooltipProps} + {...blockBtnStyle} + clickHandler={toggleSkip} + tabIndex={-1} + isDisabled={selected} + /> + } + isDisabled={skip} + {...tooltipProps} + {...blockBtnStyle} + clickHandler={() => setEventPlayback.loadEvent(eventId)} + tabIndex={-1} + /> + : } + isDisabled={skip} + {...tooltipProps} + {...blockBtnStyle} + clickHandler={() => setEventPlayback.startEvent(eventId)} + backgroundColor={isPlaying ? '#58A151' : undefined} + _hover={{ backgroundColor: isPlaying ? '#58A151' : undefined }} + tabIndex={-1} + /> +
+ ); +}; + +export default memo(EventBlockPlayback); diff --git a/apps/client/src/features/rundown/event-block/composite/EventBlockTimers.tsx b/apps/client/src/features/rundown/event-block/composite/EventBlockTimers.tsx index ff90585d6..1d935e952 100644 --- a/apps/client/src/features/rundown/event-block/composite/EventBlockTimers.tsx +++ b/apps/client/src/features/rundown/event-block/composite/EventBlockTimers.tsx @@ -1,28 +1,53 @@ -import { useCallback, useState } from 'react'; +import { memo, useCallback, useState } from 'react'; +import { OntimeEvent } from 'ontime-types'; import { millisToString } from 'ontime-utils'; import TimeInput from '../../../../common/components/input/time-input/TimeInput'; +import { useEventAction } from '../../../../common/hooks/useEventAction'; import { millisToMinutes } from '../../../../common/utils/dateConfig'; -import { TimeEntryField, validateEntry } from '../../../../common/utils/timesManager'; -import { EventItemActions } from '../../RundownEntry'; +import { calculateDuration, TimeEntryField, validateEntry } from '../../../../common/utils/timesManager'; import style from '../EventBlock.module.scss'; interface EventBlockTimerProps { + eventId: string; timeStart: number; timeEnd: number; duration: number; delay: number; - actionHandler: (action: EventItemActions, payload?: any) => void; previousEnd: number; } -export default function EventBlockTimers(props: EventBlockTimerProps) { - const { timeStart, timeEnd, duration, delay, actionHandler, previousEnd } = props; +type TimeActions = 'timeStart' | 'timeEnd' | 'durationOverride'; + +const EventBlockTimers = (props: EventBlockTimerProps) => { + const { eventId, timeStart, timeEnd, duration, delay, previousEnd } = props; + const { updateEvent } = useEventAction(); + const [warning, setWarnings] = useState({ start: '', end: '', duration: '' }); - const delayTime = `${delay >= 0 ? '+' : '-'} ${millisToMinutes(Math.abs(delay))}`; - const newTime = millisToString(timeStart + delay); + const handleSubmit = (field: TimeActions, value: number) => { + const newEventData: Partial = { id: eventId }; + switch (field) { + case 'durationOverride': { + // duration defines timeEnd + newEventData.duration = value; + newEventData.timeEnd = timeStart + value; + break; + } + case 'timeStart': { + newEventData.duration = calculateDuration(value, timeEnd); + newEventData.timeStart = value; + break; + } + case 'timeEnd': { + newEventData.duration = calculateDuration(timeStart, value); + newEventData.timeEnd = value; + break; + } + } + updateEvent(newEventData); + }; /** * @description Validates a time input against its pair @@ -39,12 +64,8 @@ export default function EventBlockTimers(props: EventBlockTimerProps) { [timeEnd, timeStart], ); - const handleSubmit = useCallback( - (field: TimeEntryField, value: number) => { - actionHandler('update', { field, value }); - }, - [actionHandler], - ); + const delayTime = `${delay >= 0 ? '+' : '-'} ${millisToMinutes(Math.abs(delay))}`; + const newTime = millisToString(timeStart + delay); return (
@@ -86,4 +107,6 @@ export default function EventBlockTimers(props: EventBlockTimerProps) { )}
); -} +}; + +export default memo(EventBlockTimers); diff --git a/apps/client/src/features/rundown/quick-add-block/QuickAddBlock.tsx b/apps/client/src/features/rundown/quick-add-block/QuickAddBlock.tsx index 7eb3eb95e..8fd208644 100644 --- a/apps/client/src/features/rundown/quick-add-block/QuickAddBlock.tsx +++ b/apps/client/src/features/rundown/quick-add-block/QuickAddBlock.tsx @@ -1,4 +1,4 @@ -import { useCallback, useRef } from 'react'; +import { memo, useCallback, useRef } from 'react'; import { Button, Checkbox, Tooltip } from '@chakra-ui/react'; import { SupportedEvent } from 'ontime-types'; @@ -17,7 +17,7 @@ interface QuickAddBlockProps { disableAddBlock: boolean; } -export default function QuickAddBlock(props: QuickAddBlockProps) { +const QuickAddBlock = (props: QuickAddBlockProps) => { const { showKbd, eventId, previousEventId, disableAddDelay = true, disableAddBlock } = props; const { addEvent } = useEventAction(); const { emitError } = useEmitLog(); @@ -117,4 +117,6 @@ export default function QuickAddBlock(props: QuickAddBlockProps) { ); -} +}; + +export default memo(QuickAddBlock);