diff --git a/apps/client/src/common/models/ViewSettings.type.ts b/apps/client/src/common/models/ViewSettings.type.ts
index 4bcca29c3..ecefd9a16 100644
--- a/apps/client/src/common/models/ViewSettings.type.ts
+++ b/apps/client/src/common/models/ViewSettings.type.ts
@@ -1,8 +1,8 @@
import { ViewSettings } from 'ontime-types';
export const viewsSettingsPlaceholder: ViewSettings = {
- dangerColor: '#ED3333',
+ dangerColor: '#ff7300',
normalColor: '#ffffffcc',
overrideStyles: false,
- warningColor: '#FFAB33',
+ warningColor: '#ffa528',
};
diff --git a/apps/client/src/common/utils/offset.ts b/apps/client/src/common/utils/offset.ts
new file mode 100644
index 000000000..37b08a32b
--- /dev/null
+++ b/apps/client/src/common/utils/offset.ts
@@ -0,0 +1,25 @@
+import { MaybeNumber } from 'ontime-types';
+import { millisToString } from 'ontime-utils';
+
+import { enDash } from './styleUtils';
+
+/**
+ * Formats offset text
+ */
+export function getOffsetText(offset: MaybeNumber): string {
+ if (offset === null) {
+ return enDash;
+ }
+
+ let offsetText = '';
+ if (offset < 0) offsetText += '-';
+ if (offset > 0) offsetText += '+';
+ offsetText += millisToString(Math.abs(offset));
+ return offsetText;
+}
+
+export function getOffsetState(offset: MaybeNumber): 'ahead' | 'behind' | 'muted' | null {
+ if (offset === null) return null;
+ if (offset === 0) return 'muted';
+ return offset < 0 ? 'behind' : 'ahead';
+}
diff --git a/apps/client/src/features/control/message/TimerPreview.tsx b/apps/client/src/features/control/message/TimerPreview.tsx
index 9178220af..9b9271d8e 100644
--- a/apps/client/src/features/control/message/TimerPreview.tsx
+++ b/apps/client/src/features/control/message/TimerPreview.tsx
@@ -42,8 +42,8 @@ export default function TimerPreview() {
const overrideColour = (() => {
// override fallback colours from starter project
- if (phase === TimerPhase.Warning) return data.warningColor ?? '#FFAB33';
- if (phase === TimerPhase.Danger) return data.dangerColor ?? '#ED3333';
+ if (phase === TimerPhase.Warning) return data.warningColor ?? '#ffa528';
+ if (phase === TimerPhase.Danger) return data.dangerColor ?? '#ff7300';
return data.normalColor ?? '#FFFC';
})();
diff --git a/apps/client/src/features/overview/CuesheetOverview.tsx b/apps/client/src/features/overview/CuesheetOverview.tsx
index 9dfe53771..dca456e39 100644
--- a/apps/client/src/features/overview/CuesheetOverview.tsx
+++ b/apps/client/src/features/overview/CuesheetOverview.tsx
@@ -2,7 +2,7 @@ import { memo, PropsWithChildren } from 'react';
import { useIsMobileScreen } from '../../common/hooks/useIsMobileScreen';
-import { ClockOverview, MetadataTimes, RuntimeOverview, StartTimes, TimerOverview } from './composite/TimeElements';
+import { ClockOverview, MetadataTimes, OffsetOverview, StartTimes, TimerOverview } from './composite/TimeElements';
import TitleOverview from './composite/TitleOverview';
import { OverviewWrapper } from './OverviewWrapper';
@@ -18,7 +18,7 @@ function CuesheetMobile({ children }: PropsWithChildren) {
return (
-
+
);
}
@@ -29,7 +29,7 @@ function CuesheetDesktop({ children }: PropsWithChildren) {
-
+
diff --git a/apps/client/src/features/overview/EditorOverview.tsx b/apps/client/src/features/overview/EditorOverview.tsx
index 2a0286121..b3ab5c9ce 100644
--- a/apps/client/src/features/overview/EditorOverview.tsx
+++ b/apps/client/src/features/overview/EditorOverview.tsx
@@ -1,6 +1,6 @@
import { memo, PropsWithChildren } from 'react';
-import { ClockOverview, MetadataTimes, ProgressOverview, RuntimeOverview, StartTimes } from './composite/TimeElements';
+import { ClockOverview, MetadataTimes, OffsetOverview, ProgressOverview, StartTimes } from './composite/TimeElements';
import TitleOverview from './composite/TitleOverview';
import { OverviewWrapper } from './OverviewWrapper';
@@ -11,7 +11,7 @@ function EditorOverview({ children }: PropsWithChildren) {
-
+
diff --git a/apps/client/src/features/overview/composite/TimeElements.tsx b/apps/client/src/features/overview/composite/TimeElements.tsx
index c62b4e704..c11716610 100644
--- a/apps/client/src/features/overview/composite/TimeElements.tsx
+++ b/apps/client/src/features/overview/composite/TimeElements.tsx
@@ -13,9 +13,10 @@ import {
useTimer,
} from '../../../common/hooks/useSocket';
import { useEntry } from '../../../common/hooks-query/useRundown';
+import { getOffsetState, getOffsetText } from '../../../common/utils/offset';
import { cx, enDash, timerPlaceholder } from '../../../common/utils/styleUtils';
import { formatTime, useTimeUntilStart } from '../../../common/utils/time';
-import { calculateEndAndDaySpan, formattedTime, getOffsetText } from '../overview.utils';
+import { calculateEndAndDaySpan, formattedTime } from '../overview.utils';
import { TimeColumn } from './TimeLayout';
@@ -193,14 +194,16 @@ export function ProgressOverview() {
return ;
}
-export function RuntimeOverview() {
+export function OffsetOverview() {
const { offset, playback } = useRuntimePlaybackOverview();
const isPlaying = isPlaybackActive(playback);
- const offsetText = getOffsetText(isPlaying ? offset : null);
- const offsetClasses = cx([style.offset, isPlaying && (offset < 0 ? style.behind : style.ahead)]);
+ const correctedOffset = offset * -1;
+ const offsetState = getOffsetState(correctedOffset);
+ const offsetClasses = cx([style.offset, offsetState && style[offsetState]]);
+ const offsetText = getOffsetText(isPlaying ? correctedOffset : null);
- return ;
+ return ;
}
export function ClockOverview() {
diff --git a/apps/client/src/features/overview/overview.utils.ts b/apps/client/src/features/overview/overview.utils.ts
index f5e175349..61eeac978 100644
--- a/apps/client/src/features/overview/overview.utils.ts
+++ b/apps/client/src/features/overview/overview.utils.ts
@@ -1,7 +1,7 @@
import { MaybeNumber, TimerType } from 'ontime-types';
import { dayInMs, millisToString } from 'ontime-utils';
-import { enDash, timerPlaceholder, timerPlaceholderMin } from '../../common/utils/styleUtils';
+import { timerPlaceholder, timerPlaceholderMin } from '../../common/utils/styleUtils';
/**
* Encapsulates the logic for formatting time in overview
@@ -24,15 +24,3 @@ export function calculateEndAndDaySpan(end: MaybeNumber): [MaybeNumber, number]
return [end, 0];
}
-
-/**
- * Formats offset text
- * @param offset
- * @returns
- */
-export function getOffsetText(offset: MaybeNumber): string {
- if (offset === null) {
- return enDash;
- }
- return millisToString(offset, { fallback: enDash });
-}
diff --git a/apps/client/src/features/rundown/entry-editor/BlockEditor.tsx b/apps/client/src/features/rundown/entry-editor/BlockEditor.tsx
index 930f59c13..fb1811c3f 100644
--- a/apps/client/src/features/rundown/entry-editor/BlockEditor.tsx
+++ b/apps/client/src/features/rundown/entry-editor/BlockEditor.tsx
@@ -53,7 +53,8 @@ export default function BlockEditor({ block }: BlockEditorProps) {
);
const isEditor = window.location.pathname.includes('editor');
- const planOffset = typeof block.targetDuration !== 'number' ? null : block.targetDuration - block.duration;
+ const planOffset = typeof block.targetDuration !== 'number' ? null : block.duration - block.targetDuration;
+ const planOffsetLabel = planOffset !== null && planOffset > 0 ? 'behind' : 'ahead';
return (
@@ -94,11 +95,8 @@ export default function BlockEditor({ block }: BlockEditorProps) {
Plan offset
- {
- // TODO: update remote data
- // TODO: remove tab index
- }
-
+
+ {planOffset !== null && planOffset > 0 ? '+' : ''}
{millisToString(planOffset, { fallback: enDash })}
diff --git a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/DurationInput.tsx b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/DurationInput.tsx
index 1d9d63a46..bb251de28 100644
--- a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/DurationInput.tsx
+++ b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/DurationInput.tsx
@@ -103,7 +103,7 @@ function DurationInput({
onClick={handleFakeFocus}
onFocus={handleFakeFocus}
muted={!lockedValue}
- delayed={delayed}
+ offset={delayed ? 'behind' : undefined}
ref={textRef}
>
{children}
diff --git a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/TextLikeInput.module.scss b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/TextLikeInput.module.scss
index cdba636fc..9a43cb6a7 100644
--- a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/TextLikeInput.module.scss
+++ b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/TextLikeInput.module.scss
@@ -14,7 +14,11 @@
overflow: hidden;
- &.delayed {
+ &.ahead {
+ color: $playback-ahead;
+ }
+
+ &.behind {
color: $ontime-delay-text;
}
diff --git a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/TextLikeInput.tsx b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/TextLikeInput.tsx
index ee0415756..d8bbe4910 100644
--- a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/TextLikeInput.tsx
+++ b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/TextLikeInput.tsx
@@ -5,29 +5,30 @@ import { cx } from '../../../../common/utils/styleUtils';
import style from './TextLikeInput.module.scss';
interface TextLikeInputProps extends HTMLAttributes {
- delayed?: boolean;
+ offset?: 'ahead' | 'behind';
muted?: boolean;
}
-const TextLikeInput = forwardRef((props: PropsWithChildren, textRef) => {
- const { delayed, muted, children, className, ...elementProps } = props;
- const ref = useRef(null);
- const classes = cx([style.textInput, delayed && style.delayed, muted && style.muted, className]);
+const TextLikeInput = forwardRef(
+ ({ offset, muted, children, className, ...elementProps }: PropsWithChildren, textRef) => {
+ const ref = useRef(null);
+ const classes = cx([style.textInput, offset && style[offset], muted && style.muted, className]);
- useImperativeHandle(textRef, () => {
- return {
- focusParentElement() {
- ref.current?.parentElement?.focus();
- },
- };
- });
+ useImperativeHandle(textRef, () => {
+ return {
+ focusParentElement() {
+ ref.current?.parentElement?.focus();
+ },
+ };
+ });
- return (
-
- {children}
-
- );
-});
+ return (
+
+ {children}
+
+ );
+ },
+);
TextLikeInput.displayName = 'TextLikeInput';
diff --git a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/TimeInput.tsx b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/TimeInput.tsx
index f4c914da0..7e89967be 100644
--- a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/TimeInput.tsx
+++ b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/TimeInput.tsx
@@ -105,7 +105,7 @@ function TimeInputDuration({
onClick={handleFakeFocus}
onFocus={handleFakeFocus}
muted={!lockedValue}
- delayed={delayed}
+ offset={delayed ? 'behind' : undefined}
ref={textRef}
>
{children}
diff --git a/apps/client/src/views/studio/StudioTimers.tsx b/apps/client/src/views/studio/StudioTimers.tsx
index b2ff9cd94..7f25299b6 100644
--- a/apps/client/src/views/studio/StudioTimers.tsx
+++ b/apps/client/src/views/studio/StudioTimers.tsx
@@ -2,6 +2,7 @@ import { OntimeEvent, Playback, Runtime, TimerPhase, TimerState, ViewSettings }
import { millisToString } from 'ontime-utils';
import { useAuxTimersTime } from '../../common/hooks/useSocket';
+import { getOffsetState } from '../../common/utils/offset';
import { cx } from '../../common/utils/styleUtils';
import { useTranslation } from '../../translation/TranslationProvider';
import { getTimerColour } from '../utils/presentation.utils';
@@ -45,6 +46,8 @@ export default function StudioTimers({
time.phase === TimerPhase.Danger,
);
+ const offsetState = getOffsetState(runtime.offset);
+
return (
@@ -54,15 +57,8 @@ export default function StudioTimers({
{schedule.actualStart}
-
Offset
-
+
Over / under
+
{schedule.offset}
diff --git a/apps/client/src/views/studio/studioTimers.utils.ts b/apps/client/src/views/studio/studioTimers.utils.ts
index 76984891c..3baa511b0 100644
--- a/apps/client/src/views/studio/studioTimers.utils.ts
+++ b/apps/client/src/views/studio/studioTimers.utils.ts
@@ -1,14 +1,16 @@
import { OntimeEvent, Runtime, TimerState } from 'ontime-types';
import { millisToString } from 'ontime-utils';
+import { getOffsetText } from '../../common/utils/offset';
import { formatTime } from '../../common/utils/time';
const timeFormat = { format12: 'h:mm a', format24: 'HH:mm' };
export function getFormattedScheduleTimes(runtime: Runtime) {
+ const correctedOffset = runtime.offset !== null ? runtime.offset * -1 : null;
return {
actualStart: formatTime(runtime.actualStart, timeFormat),
expectedEnd: formatTime(runtime.expectedEnd, timeFormat),
- offset: millisToString(runtime.offset),
+ offset: getOffsetText(correctedOffset),
};
}
diff --git a/apps/server/src/models/dataModel.ts b/apps/server/src/models/dataModel.ts
index 26f0cfb6d..47abd6668 100644
--- a/apps/server/src/models/dataModel.ts
+++ b/apps/server/src/models/dataModel.ts
@@ -33,8 +33,8 @@ export const dbModel: DatabaseModel = {
viewSettings: {
overrideStyles: false,
normalColor: '#ffffffcc',
- warningColor: '#FFAB33',
- dangerColor: '#ED3333',
+ warningColor: '#ffa528',
+ dangerColor: '#ff7300',
},
urlPresets: [],
customFields: {},
diff --git a/apps/server/src/models/demoProject.ts b/apps/server/src/models/demoProject.ts
index 84e85f67a..9798ae9f5 100644
--- a/apps/server/src/models/demoProject.ts
+++ b/apps/server/src/models/demoProject.ts
@@ -532,10 +532,10 @@ export const demoDb: DatabaseModel = {
language: 'en',
},
viewSettings: {
- dangerColor: '#ED3333',
+ dangerColor: '#ff7300',
normalColor: '#ffffffcc',
overrideStyles: false,
- warningColor: '#FFAB33',
+ warningColor: '#ffa528',
},
customFields: {
Song: {
diff --git a/apps/server/test-db/db.json b/apps/server/test-db/db.json
index 9dc56a557..ba99145cd 100644
--- a/apps/server/test-db/db.json
+++ b/apps/server/test-db/db.json
@@ -467,10 +467,10 @@
"language": "en"
},
"viewSettings": {
- "dangerColor": "#ED3333",
+ "dangerColor": "#ff7300",
"normalColor": "#ffffffcc",
"overrideStyles": false,
- "warningColor": "#FFAB33"
+ "warningColor": "#ffa528"
},
"customFields": {
"song": {
diff --git a/e2e/tests/fixtures/e2e-test-db.json b/e2e/tests/fixtures/e2e-test-db.json
index 8cc730fcf..004934c52 100644
--- a/e2e/tests/fixtures/e2e-test-db.json
+++ b/e2e/tests/fixtures/e2e-test-db.json
@@ -484,10 +484,10 @@
"language": "en"
},
"viewSettings": {
- "dangerColor": "#ED3333",
+ "dangerColor": "#ff7300",
"normalColor": "#ffffffcc",
"overrideStyles": false,
- "warningColor": "#FFAB33"
+ "warningColor": "#ffa528"
},
"customFields": {
"Song": {