End pause (#832)

* refactor: trigger ahead

* refactor: refresh often

* fix: handle empty rundown updates

* fix: handle falsy values

* style: avoid overlap of components

* refactor: freeze end option
This commit is contained in:
Carlos Valente
2024-03-19 18:04:05 +01:00
committed by GitHub
parent 8156da03d5
commit 4bb836b6f2
18 changed files with 89 additions and 39 deletions
@@ -1,9 +1,10 @@
import { ViewSettings } from 'ontime-types';
export const viewsSettingsPlaceholder: ViewSettings = {
overrideStyles: false,
normalColor: '#ffffffcc',
warningColor: '#FFAB33',
dangerColor: '#ED3333',
endMessage: '',
freezeEnd: false,
normalColor: '#ffffffcc',
overrideStyles: false,
warningColor: '#FFAB33',
};
@@ -1,7 +1,7 @@
.corner {
position: absolute;
top: 1rem;
right: 1rem;
right: 2rem;
z-index: 100;
}
@@ -118,7 +118,17 @@ export default function ViewSettingsForm() {
</Panel.ListGroup>
<Panel.ListGroup>
<Panel.ListItem>
<Panel.Field title='End message' description='If no end message is provided, timer will continue' />
<Panel.Field
title='Freeze timer on end'
description='Timer in views will stop from going negative after reaching'
/>
<Switch {...register('freezeEnd')} variant='ontime' size='lg' />
</Panel.ListItem>
<Panel.ListItem>
<Panel.Field
title='End message'
description='Message to show on negative timers if not frozen. If not provided, timer will continue'
/>
<Input
size='sm'
autoComplete='off'
@@ -4,7 +4,7 @@ import type { ViewExtendedTimer } from '../../../common/models/TimeManager.type'
type TimerTypeParams = Pick<ViewExtendedTimer, 'timerType' | 'current' | 'elapsed' | 'clock'>;
export function getTimerByType(timerObject?: TimerTypeParams): number | null {
export function getTimerByType(freezeEnd: boolean, timerObject?: TimerTypeParams): number | null {
if (!timerObject) {
return null;
}
@@ -12,7 +12,10 @@ export function getTimerByType(timerObject?: TimerTypeParams): number | null {
switch (timerObject.timerType) {
case TimerType.CountDown:
case TimerType.TimeToEnd:
return timerObject.current;
if (timerObject.current === null) {
return null;
}
return freezeEnd ? Math.max(timerObject.current, 0) : timerObject.current;
case TimerType.CountUp:
return Math.abs(timerObject.elapsed ?? 0);
case TimerType.Clock:
@@ -1,7 +1,7 @@
import { useEffect } from 'react';
import { useSearchParams } from 'react-router-dom';
import { Playback, TimerMessage, TimerType, ViewSettings } from 'ontime-types';
import { millisToString, removeLeadingZero, removeSeconds } from 'ontime-utils';
import { MILLIS_PER_SECOND, millisToString, removeLeadingZero, removeSeconds } from 'ontime-utils';
import { overrideStylesURL } from '../../../common/api/constants';
import NavigationMenu from '../../../common/components/navigation-menu/NavigationMenu';
@@ -150,7 +150,7 @@ export default function MinimalTimer(props: MinimalTimerProps) {
if (!timerIsTimeOfDay && showProgress && showWarning) timerColor = viewSettings.warningColor;
if (!timerIsTimeOfDay && showProgress && showDanger) timerColor = viewSettings.dangerColor;
const stageTimer = getTimerByType(time);
const stageTimer = getTimerByType(viewSettings.freezeEnd, time);
let display = millisToString(stageTimer, { fallback: timerPlaceholder });
if (stageTimer !== null) {
if (hideTimerSeconds) {
@@ -158,7 +158,8 @@ export default function MinimalTimer(props: MinimalTimerProps) {
}
display = removeLeadingZero(display);
// last unit rounds up in negative timers
const isNegative = (stageTimer ?? 0 < 0) && !timerIsTimeOfDay && time.timerType !== TimerType.CountUp;
const isNegative =
(stageTimer ?? 0 < MILLIS_PER_SECOND) && !timerIsTimeOfDay && time.timerType !== TimerType.CountUp;
if (isNegative && display === '0') {
display = '-1';
}
@@ -11,7 +11,7 @@ import {
TimerType,
ViewSettings,
} from 'ontime-types';
import { millisToString, removeLeadingZero, removeSeconds } from 'ontime-utils';
import { MILLIS_PER_SECOND, millisToString, removeLeadingZero, removeSeconds } from 'ontime-utils';
import { overrideStylesURL } from '../../../common/api/constants';
import MultiPartProgressBar from '../../../common/components/multi-part-progress-bar/MultiPartProgressBar';
@@ -59,6 +59,7 @@ interface TimerProps {
export default function Timer(props: TimerProps) {
const { customFields, isMirrored, pres, eventNow, eventNext, time, viewSettings, external, settings } = props;
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
const { getLocalizedString } = useTranslation();
const [searchParams] = useSearchParams();
@@ -127,7 +128,7 @@ export default function Timer(props: TimerProps) {
if (!timerIsTimeOfDay && showProgress && showWarning) timerColor = viewSettings.warningColor;
if (!timerIsTimeOfDay && showProgress && showDanger) timerColor = viewSettings.dangerColor;
const stageTimer = getTimerByType(time);
const stageTimer = getTimerByType(viewSettings.freezeEnd, time);
let display = millisToString(stageTimer, { fallback: timerPlaceholder });
if (stageTimer !== null) {
if (hideTimerSeconds) {
@@ -135,7 +136,8 @@ export default function Timer(props: TimerProps) {
}
display = removeLeadingZero(display);
// last unit rounds up in negative timers
const isNegative = (stageTimer ?? 0 < 0) && !timerIsTimeOfDay && time.timerType !== TimerType.CountUp;
const isNegative =
(stageTimer ?? 0 < -MILLIS_PER_SECOND) && !timerIsTimeOfDay && time.timerType !== TimerType.CountUp;
if (isNegative && display === '0') {
display = '-1';
}
@@ -215,7 +217,7 @@ export default function Timer(props: TimerProps) {
{!userOptions.hideCards && (
<>
<AnimatePresence>
{eventNow && (
{eventNow?.title && (
<motion.div
className='event now'
key='now'
@@ -230,7 +232,7 @@ export default function Timer(props: TimerProps) {
</AnimatePresence>
<AnimatePresence>
{eventNext && (
{eventNext?.title && (
<motion.div
className='event next'
key='next'