diff --git a/apps/client/src/common/hooks/useSocket.ts b/apps/client/src/common/hooks/useSocket.ts
index 06948c53d..1ccbec87a 100644
--- a/apps/client/src/common/hooks/useSocket.ts
+++ b/apps/client/src/common/hooks/useSocket.ts
@@ -250,3 +250,11 @@ export const useIsOnline = () => {
return useRuntimeStore(featureSelector);
};
+
+export const usePlayback = () => {
+ const featureSelector = (state: RuntimeStore) => ({
+ playback: state.timer.playback,
+ });
+
+ return useRuntimeStore(featureSelector);
+};
diff --git a/apps/client/src/features/rundown/Rundown.tsx b/apps/client/src/features/rundown/Rundown.tsx
index 7099ab0f1..6106900cd 100644
--- a/apps/client/src/features/rundown/Rundown.tsx
+++ b/apps/client/src/features/rundown/Rundown.tsx
@@ -269,6 +269,7 @@ export default function Rundown({ data }: RundownProps) {
// all events before the current selected are in the past
let isPast = Boolean(featureData?.selectedEventId);
let isNextDay = false;
+ let totalGap = 0;
const isEditMode = appMode === AppMode.Edit;
return (
@@ -297,6 +298,7 @@ export default function Rundown({ data }: RundownProps) {
if (isPlayableEvent(entry)) {
isNextDay = checkIsNextDay(entry, lastEvent);
+ totalGap += !isPast ? entry.gap : 0;
if (isNewLatest(entry, lastEvent)) {
// populate previous entry
thisEvent = entry;
@@ -331,6 +333,7 @@ export default function Rundown({ data }: RundownProps) {
playback={isLoaded ? featureData.playback : undefined}
isRolling={featureData.playback === Playback.Roll}
isNextDay={isNextDay}
+ totalGap={totalGap}
/>
diff --git a/apps/client/src/features/rundown/RundownEntry.tsx b/apps/client/src/features/rundown/RundownEntry.tsx
index d7fb2ce7d..386950aa5 100644
--- a/apps/client/src/features/rundown/RundownEntry.tsx
+++ b/apps/client/src/features/rundown/RundownEntry.tsx
@@ -37,6 +37,7 @@ interface RundownEntryProps {
previousEventId?: string;
playback?: Playback; // we only care about this if this event is playing
isRolling: boolean; // we need to know even if not related to this event
+ totalGap: number;
}
export default function RundownEntry(props: RundownEntryProps) {
@@ -52,6 +53,7 @@ export default function RundownEntry(props: RundownEntryProps) {
isRolling,
eventIndex,
isNextDay,
+ totalGap,
} = props;
const { emitError } = useEmitLog();
const { addEvent, updateEvent, batchUpdateEvents, deleteEvent, swapEvents } = useEventAction();
@@ -173,6 +175,8 @@ export default function RundownEntry(props: RundownEntryProps) {
isRolling={isRolling}
gap={data.gap}
isNextDay={isNextDay}
+ dayOffset={data.dayOffset}
+ totalGap={totalGap}
actionHandler={actionHandler}
/>
);
diff --git a/apps/client/src/features/rundown/event-block/EventBlock.module.scss b/apps/client/src/features/rundown/event-block/EventBlock.module.scss
index 2328b52e0..1ee1bb917 100644
--- a/apps/client/src/features/rundown/event-block/EventBlock.module.scss
+++ b/apps/client/src/features/rundown/event-block/EventBlock.module.scss
@@ -9,7 +9,7 @@ $skip-opacity: 0.2;
display: grid;
grid-template-areas:
'binder ... ... ...'
- 'binder pb-actions times ...'
+ 'binder pb-actions times chip'
'binder pb-actions title title'
'binder pb-actions estatus estatus'
'binder ... ... ...';
@@ -131,6 +131,10 @@ $skip-opacity: 0.2;
height: 100%;
}
+.chipSection {
+ grid-area: chip;
+}
+
.titleSection {
grid-area: title;
display: flex;
diff --git a/apps/client/src/features/rundown/event-block/EventBlock.tsx b/apps/client/src/features/rundown/event-block/EventBlock.tsx
index 1f1de2ef3..8fd2fc4ea 100644
--- a/apps/client/src/features/rundown/event-block/EventBlock.tsx
+++ b/apps/client/src/features/rundown/event-block/EventBlock.tsx
@@ -49,6 +49,8 @@ interface EventBlockProps {
isRolling: boolean;
gap: number;
isNextDay: boolean;
+ dayOffset: number;
+ totalGap: number;
actionHandler: (
action: EventItemActions,
payload?:
@@ -87,6 +89,8 @@ export default function EventBlock(props: EventBlockProps) {
isRolling,
gap,
isNextDay,
+ dayOffset,
+ totalGap,
actionHandler,
} = props;
const { selectedEventId, setSelectedEventId, clearSelectedEventId } = useEventIdSwapping();
@@ -303,6 +307,9 @@ export default function EventBlock(props: EventBlockProps) {
loaded={loaded}
playback={playback}
isRolling={isRolling}
+ dayOffset={dayOffset}
+ isPast={isPast}
+ totalGap={totalGap}
/>
)}
diff --git a/apps/client/src/features/rundown/event-block/EventBlockInner.tsx b/apps/client/src/features/rundown/event-block/EventBlockInner.tsx
index 6d64376fa..a59450486 100644
--- a/apps/client/src/features/rundown/event-block/EventBlockInner.tsx
+++ b/apps/client/src/features/rundown/event-block/EventBlockInner.tsx
@@ -11,12 +11,14 @@ import { IoPlaySkipForward } from '@react-icons/all-files/io5/IoPlaySkipForward'
import { IoStop } from '@react-icons/all-files/io5/IoStop';
import { IoTime } from '@react-icons/all-files/io5/IoTime';
import { EndAction, MaybeString, Playback, TimerType, TimeStrategy } from 'ontime-types';
+import { dayInMs } from 'ontime-utils';
import { cx } from '../../../common/utils/styleUtils';
import { tooltipDelayMid } from '../../../ontimeConfig';
import EditableBlockTitle from '../common/EditableBlockTitle';
import TimeInputFlow from '../time-input-flow/TimeInputFlow';
+import EventBlockChip from './composite/EventBlockChip';
import EventBlockPlayback from './composite/EventBlockPlayback';
import EventBlockProgressBar from './composite/EventBlockProgressBar';
@@ -42,6 +44,9 @@ interface EventBlockInnerProps {
loaded: boolean;
playback?: Playback;
isRolling: boolean;
+ dayOffset: number;
+ isPast: boolean;
+ totalGap: number;
}
function EventBlockInner(props: EventBlockInnerProps) {
@@ -64,6 +69,9 @@ function EventBlockInner(props: EventBlockInnerProps) {
loaded,
playback,
isRolling,
+ dayOffset,
+ isPast,
+ totalGap,
} = props;
const [renderInner, setRenderInner] = useState(false);
@@ -108,6 +116,17 @@ function EventBlockInner(props: EventBlockInnerProps) {
loaded={loaded}
disablePlayback={skip || isRolling}
/>
+ {!skip && (
+