Feat/countdown style (#290)

* feat: Countdown Style

---------

Co-authored-by: Fabian Posenau <fabian@fphome.de>
Co-authored-by: cv <34649812+cpvalente@users.noreply.github.com>
Co-authored-by: Fabian Posenau <19673098+kellhogs@users.noreply.github.com>
This commit is contained in:
Fabian Posenau
2023-02-26 19:53:26 +01:00
committed by GitHub
parent 6d138ce9f1
commit c405698813
16 changed files with 228 additions and 139 deletions
@@ -3,17 +3,11 @@
.timer { .timer {
font-family: var(--font-family-override, $viewer-font-family); font-family: var(--font-family-override, $viewer-font-family);
color: var(--timer-color-override, $timer-color); color: var(--timer-color-override, $timer-color);
font-size: 20vw;
line-height: 0.9em; line-height: 0.9em;
text-align: center; text-align: center;
letter-spacing: 0.05em; letter-spacing: 0.1em;
font-weight: 600; font-weight: 600;
font-size: 3.75em;
&--small {
font-size: 3.75em;
text-align: center;
letter-spacing: 0.1em;
}
&--finished { &--finished {
color: $timer-finished-color; color: $timer-finished-color;
@@ -6,9 +6,6 @@ import './TimerDisplay.scss';
interface TimerDisplayProps { interface TimerDisplayProps {
time?: number | null; time?: number | null;
small?: boolean;
hideZeroHours?: boolean;
className?: string;
} }
/** /**
@@ -17,15 +14,19 @@ interface TimerDisplayProps {
* @constructor * @constructor
*/ */
const TimerDisplay = (props: TimerDisplayProps) => { const TimerDisplay = (props: TimerDisplayProps) => {
const { time, small, hideZeroHours, className = '' } = props; const { time } = props;
const display = let display = '';
(time === null || typeof time === 'undefined' || isNaN(time))
? '-- : -- : --' if (time === null || typeof time === 'undefined' || isNaN(time)) {
: formatDisplay(millisToSeconds(time), hideZeroHours); display = '-- : -- : --';
} else {
display = formatDisplay(millisToSeconds(time));
}
const isNegative = (time ?? 0) < 0; const isNegative = (time ?? 0) < 0;
const classes = `timer ${small ? 'timer--small' : ''} ${isNegative ? 'timer--finished' : ''} ${className}`;
const classes = `timer ${isNegative ? 'timer--finished' : ''}`;
return <div className={classes}>{display}</div>; return <div className={classes}>{display}</div>;
}; };
@@ -1,9 +1,12 @@
import { Playback } from 'ontime-types'; import { Playback, TimerType } from 'ontime-types';
export type TimeManagerType = { export type TimeManagerType = {
clock: number; clock: number;
current: null | number; current: null | number;
elapsed: null | number; elapsed: null | number;
duration: null | number;
timerBehaviour?: string;
timerType: TimerType;
expectedFinish: null | number; expectedFinish: null | number;
addedTime: number; addedTime: number;
startedAt: null | number; startedAt: null | number;
@@ -44,7 +44,7 @@ export default function PlaybackTimer(props: PlaybackTimerProps) {
</Tooltip> </Tooltip>
</div> </div>
<div className={style.timer}> <div className={style.timer}>
<TimerDisplay time={isWaiting ? timerData.secondaryTimer : timerData.current} small /> <TimerDisplay time={isWaiting ? timerData.secondaryTimer : timerData.current} />
</div> </div>
{isWaiting ? ( {isWaiting ? (
<div className={style.roll}> <div className={style.roll}>
@@ -2,7 +2,7 @@ import { useCallback, useContext, useEffect, useState } from 'react';
import { Button, Select, Switch } from '@chakra-ui/react'; import { Button, Select, Switch } from '@chakra-ui/react';
import { IoBan } from '@react-icons/all-files/io5/IoBan'; import { IoBan } from '@react-icons/all-files/io5/IoBan';
import { useAtom } from 'jotai'; import { useAtom } from 'jotai';
import { OntimeEvent } from 'ontime-types'; import { OntimeEvent, TimerType } from 'ontime-types';
import { editorEventId } from '../../common/atoms/LocalEventSettings'; import { editorEventId } from '../../common/atoms/LocalEventSettings';
import CopyTag from '../../common/components/copy-tag/CopyTag'; import CopyTag from '../../common/components/copy-tag/CopyTag';
@@ -84,7 +84,8 @@ export default function EventEditor() {
[emitError, event, updateEvent], [emitError, event, updateEvent],
); );
const timerValidationHandler = useCallback((entry: TimeEntryField, val: number) => { const timerValidationHandler = useCallback(
(entry: TimeEntryField, val: number) => {
if (!event) { if (!event) {
return; return;
} }
@@ -97,7 +98,15 @@ export default function EventEditor() {
[event, emitWarning], [event, emitWarning],
); );
const togglePublic = useCallback((currentValue: boolean) => { const handleChange = useCallback(
(field: string, value: string) => {
updateEvent({ id: event.id, [field]: value });
},
[event, updateEvent],
);
const togglePublic = useCallback(
(currentValue: boolean) => {
if (!event) { if (!event) {
return; return;
} }
@@ -111,9 +120,7 @@ export default function EventEditor() {
} }
const delayed = delay !== 0; const delayed = delay !== 0;
const addedTime = delayed const addedTime = delayed ? `${delay >= 0 ? '+' : '-'} ${millisToMinutes(Math.abs(delay))} minutes` : null;
? `${delay >= 0 ? '+' : '-'} ${millisToMinutes(Math.abs(delay))} minutes`
: null;
const newStart = delayed ? `New start ${stringFromMillis(event.timeStart + delay)}` : null; const newStart = delayed ? `New start ${stringFromMillis(event.timeStart + delay)}` : null;
const newEnd = delayed ? `New end ${stringFromMillis(event.timeEnd + delay)}` : null; const newEnd = delayed ? `New end ${stringFromMillis(event.timeEnd + delay)}` : null;
@@ -162,26 +169,32 @@ export default function EventEditor() {
/> />
</div> </div>
<div className={style.timeSettings}> <div className={style.timeSettings}>
<label className={style.inputLabel}>Timer type</label> <label className={style.inputLabel}>Timer Behaviour</label>
<Select size='sm' variant='ontime'> <Select
<option value='option1'>Start to end</option> size='sm'
<option value='option2'>Duration</option> name='timerBehaviour'
<option value='option3'>Follow previous</option> value={event.timerBehaviour}
<option value='option3'>Start only</option> onChange={(event) => handleChange('timerBehaviour', event.target.value)}
>
<option value='start-end'>Start to end</option>
<option value='duration'>Duration</option>
<option value='follow-previous'>Follow previous</option>
<option value='start-only'>Start only</option>
</Select> </Select>
<label className={style.inputLabel}>Countdown style</label> <label className={style.inputLabel}>Timer Type</label>
<Select size='sm' variant='ontime'> <Select
<option value='option1'>Count down</option> size='sm'
<option value='option2'>Count up</option> name='timerType'
<option value='option3'>Clock</option> value={event.timerType}
onChange={(event) => handleChange('timerType', event.target.value)}
>
<option value={TimerType.CountDown}>Count down</option>
<option value={TimerType.CountUp}>Count up</option>
<option value={TimerType.Clock}>Clock</option>
</Select> </Select>
<span className={style.spacer} /> <span className={style.spacer} />
<label className={`${style.inputLabel} ${style.publicToggle}`}> <label className={`${style.inputLabel} ${style.publicToggle}`}>
<Switch <Switch isChecked={event.isPublic} onChange={() => togglePublic(event.isPublic)} variant='ontime' />
isChecked={event.isPublic}
onChange={() => togglePublic(event.isPublic)}
variant='ontime'
/>
Event is public Event is public
</label> </label>
</div> </div>
@@ -194,11 +207,7 @@ export default function EventEditor() {
</div> </div>
<div className={style.column}> <div className={style.column}>
<label className={style.inputLabel}>Presenter</label> <label className={style.inputLabel}>Presenter</label>
<TextInput <TextInput field='presenter' initialText={event.presenter} submitHandler={handleSubmit} />
field='presenter'
initialText={event.presenter}
submitHandler={handleSubmit}
/>
</div> </div>
<div className={style.column}> <div className={style.column}>
<label className={style.inputLabel}>Subtitle</label> <label className={style.inputLabel}>Subtitle</label>
@@ -209,30 +218,15 @@ export default function EventEditor() {
<div className={style.column}> <div className={style.column}>
<label className={style.inputLabel}>Colour</label> <label className={style.inputLabel}>Colour</label>
<div className={style.inline}> <div className={style.inline}>
<ColourInput <ColourInput name='colour' value={event?.colour} handleChange={handleSubmit} />
name="colour" <Button leftIcon={<IoBan />} onClick={() => handleSubmit('colour', '')} variant='ontime-subtle' size='sm'>
value={event?.colour}
handleChange={handleSubmit}
/>
<Button
leftIcon={<IoBan />}
onClick={() => handleSubmit('colour', '')}
variant='ontime-subtle'
size='sm'
>
Clear colour Clear colour
</Button> </Button>
</div> </div>
</div> </div>
<div className={`${style.column} ${style.fullHeight}`}> <div className={`${style.column} ${style.fullHeight}`}>
<label className={style.inputLabel}>Note</label> <label className={style.inputLabel}>Note</label>
<TextInput <TextInput field='note' initialText={event.note} submitHandler={handleSubmit} isTextArea isFullHeight />
field='note'
initialText={event.note}
submitHandler={handleSubmit}
isTextArea
isFullHeight
/>
</div> </div>
</div> </div>
</div> </div>
@@ -0,0 +1,44 @@
import { TimerType } from 'ontime-types';
import { TimeManagerType } from '../../../common/models/TimeManager.type';
import { formatDisplay, millisToSeconds } from '../../../common/utils/dateConfig';
import { formatTime } from '../../../common/utils/time';
const formatOptions = {
showSeconds: true,
format: 'hh:mm:ss a',
};
type TimerTypeParams = Pick<TimeManagerType, 'timerType' | 'current' | 'elapsed' | 'clock'>;
export function getTimerByType(timerObject?: TimerTypeParams): string | number | null {
let timer = null;
if (!timerObject) {
return timer;
}
if (timerObject.timerType === TimerType.CountDown) {
timer = timerObject.current;
} else if (timerObject.timerType === TimerType.CountUp) {
//todo: fix counting down issue in backend later
timer = (timerObject.elapsed ?? 0) < 0 ? 0 : timerObject.elapsed;
} else if (timerObject.timerType === TimerType.Clock) {
timer = formatTime(timerObject.clock, formatOptions);
}
return timer;
}
export function formatTimerDisplay(timer?: string | number | null): string {
let display = '';
if (typeof timer === 'string') {
display = timer;
} else if (timer === null || typeof timer === 'undefined' || isNaN(timer)) {
display = '-- : -- : --';
} else {
display = formatDisplay(millisToSeconds(timer), true);
}
return display;
}
@@ -1,7 +1,7 @@
import { useEffect } from 'react'; import { useEffect } from 'react';
import { useSearchParams } from 'react-router-dom'; import { useSearchParams } from 'react-router-dom';
import { useAtom } from 'jotai'; import { useAtom } from 'jotai';
import { EventData, Message, ViewSettings } from 'ontime-types'; import { EventData, Message, TimerType, ViewSettings } from 'ontime-types';
import { overrideStylesURL } from '../../../common/api/apiConstants'; import { overrideStylesURL } from '../../../common/api/apiConstants';
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings'; import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
@@ -9,7 +9,7 @@ import NavigationMenu from '../../../common/components/navigation-menu/Navigatio
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet'; import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
import { TimeManagerType } from '../../../common/models/TimeManager.type'; import { TimeManagerType } from '../../../common/models/TimeManager.type';
import { OverridableOptions } from '../../../common/models/View.types'; import { OverridableOptions } from '../../../common/models/View.types';
import { formatDisplay, millisToSeconds } from '../../../common/utils/dateConfig'; import { formatTimerDisplay, getTimerByType } from '../common/viewerUtils';
import './MinimalTimer.scss'; import './MinimalTimer.scss';
@@ -128,23 +128,24 @@ export default function MinimalTimer(props: MinimalTimerProps) {
const showOverlay = pres.text !== '' && pres.visible; const showOverlay = pres.text !== '' && pres.visible;
const isPlaying = time.playback !== 'pause'; const isPlaying = time.playback !== 'pause';
const isNegative = (time.current ?? 0) < 0; const isNegative =
const showFinished = isNegative && !userOptions?.hideOvertime; (time.current ?? 0) < 0 && time.timerType !== TimerType.Clock && time.timerType !== TimerType.CountUp;
const showEndMessage = time.current < 0 && general.endMessage && !hideEndMessage; const showEndMessage = time.current < 0 && general.endMessage && !hideEndMessage;
const showFinished =
time.finished && !userOptions?.hideOvertime && (time.timerType !== TimerType.Clock || showEndMessage);
const stageTimer = getTimerByType(time);
let display = formatTimerDisplay(stageTimer);
if (isNegative) {
display = `-${display}`;
}
const stageTimerCharacters = display.replace('/:/g', '').length;
const timerFontSize = (89 / (stageTimerCharacters - 1)) * (userOptions.size || 1);
const timerClasseNames = `timer ${!isPlaying ? 'timer--paused' : ''} ${showFinished ? 'timer--finished' : ''}`;
const baseClasses = `minimal-timer ${isMirrored ? 'mirror' : ''}`; const baseClasses = `minimal-timer ${isMirrored ? 'mirror' : ''}`;
let stageTimer;
if (time.current === null) {
stageTimer = '- - : - -';
} else {
stageTimer = formatDisplay(Math.abs(millisToSeconds(time.current)), true);
if (time.current < 0) {
stageTimer = `-${stageTimer}`;
}
}
const stageTimerCharacters = stageTimer.replace('/:/g', '').length;
return ( return (
<div <div
className={showFinished ? `${baseClasses} minimal-timer--finished` : baseClasses} className={showFinished ? `${baseClasses} minimal-timer--finished` : baseClasses}
@@ -165,17 +166,17 @@ export default function MinimalTimer(props: MinimalTimerProps) {
<div className='end-message'>{general.endMessage}</div> <div className='end-message'>{general.endMessage}</div>
) : ( ) : (
<div <div
className={`timer ${!isPlaying ? 'timer--paused' : ''} ${showFinished ? 'timer--finished' : ''}`} className={timerClasseNames}
style={{ style={{
color: userOptions.textColour, color: userOptions.textColour,
fontSize: `${(89 / (stageTimerCharacters - 1)) * (userOptions.size || 1)}vw`, fontSize: `${timerFontSize}vw`,
fontFamily: userOptions.font, fontFamily: userOptions.font,
top: userOptions.top, top: userOptions.top,
left: userOptions.left, left: userOptions.left,
backgroundColor: userOptions.textBackground, backgroundColor: userOptions.textBackground,
}} }}
> >
{stageTimer} {display}
</div> </div>
)} )}
</div> </div>
@@ -35,6 +35,7 @@
grid-area: clock; grid-area: clock;
margin-left: auto; margin-left: auto;
font-weight: 600; font-weight: 600;
transition: opacity $viewer-transition-time;
.label { .label {
font-size: clamp(16px, 1.5vw, 24px); font-size: clamp(16px, 1.5vw, 24px);
@@ -47,6 +48,10 @@
color: var(--secondary-color-override, $viewer-secondary-color); color: var(--secondary-color-override, $viewer-secondary-color);
letter-spacing: 0.05em; letter-spacing: 0.05em;
} }
&--hidden {
opacity: 0;
}
} }
/* =================== TITLES ===================*/ /* =================== TITLES ===================*/
@@ -71,7 +76,6 @@
grid-area: timer; grid-area: timer;
justify-self: center; justify-self: center;
align-self: center; align-self: center;
color: var(--timer-color-override, $timer-color);
.end-message { .end-message {
text-align: center; text-align: center;
@@ -84,6 +88,22 @@
.timer { .timer {
opacity: 1; opacity: 1;
font-size: 20vw;
font-family: var(--font-family-override, $viewer-font-family);
color: var(--timer-color-override, $timer-color);
line-height: 0.9em;
text-align: center;
letter-spacing: 0.05em;
font-weight: 600;
&--paused {
opacity: $viewer-opacity-disabled;
transition: $viewer-transition-time;
}
&--finished {
color: $timer-finished-color;
}
} }
} }
@@ -93,13 +113,12 @@
margin: 0 auto; margin: 0 auto;
opacity: 1; opacity: 1;
transition: $viewer-transition-time; transition: $viewer-transition-time;
}
.timer--paused, &--paused {
.progress-container--paused {
opacity: $viewer-opacity-disabled; opacity: $viewer-opacity-disabled;
transition: $viewer-transition-time; transition: $viewer-transition-time;
} }
}
/* =================== OVERLAY ===================*/ /* =================== OVERLAY ===================*/
@@ -1,16 +1,17 @@
import { useEffect } from 'react'; import { useEffect } from 'react';
import { AnimatePresence, motion } from 'framer-motion'; import { AnimatePresence, motion } from 'framer-motion';
import { useAtom } from 'jotai'; import { useAtom } from 'jotai';
import { TimerType } from 'ontime-types';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { overrideStylesURL } from '../../../common/api/apiConstants'; import { overrideStylesURL } from '../../../common/api/apiConstants';
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings'; import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
import NavigationMenu from '../../../common/components/navigation-menu/NavigationMenu'; import NavigationMenu from '../../../common/components/navigation-menu/NavigationMenu';
import ProgressBar from '../../../common/components/progress-bar/ProgressBar'; import ProgressBar from '../../../common/components/progress-bar/ProgressBar';
import TimerDisplay from '../../../common/components/timer-display/TimerDisplay';
import TitleCard from '../../../common/components/title-card/TitleCard'; import TitleCard from '../../../common/components/title-card/TitleCard';
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet'; import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
import { formatTime } from '../../../common/utils/time'; import { formatTime } from '../../../common/utils/time';
import { formatTimerDisplay, getTimerByType } from '../common/viewerUtils';
import './Timer.scss'; import './Timer.scss';
@@ -61,29 +62,49 @@ export default function Timer(props) {
const clock = formatTime(time.clock, formatOptions); const clock = formatTime(time.clock, formatOptions);
const showOverlay = pres.text !== '' && pres.visible; const showOverlay = pres.text !== '' && pres.visible;
const isPlaying = time.playback !== 'pause'; const isPlaying = time.playback !== 'pause';
const normalisedTime = time.current === null ? null : Math.max(time.current, 0); const isNegative =
(time.current ?? 0) < 0 && time.timerType !== TimerType.Clock && time.timerType !== TimerType.CountUp;
const showEndMessage = time.current < 0 && general.endMessage;
const showProgress = time.playback !== 'stop'; const showProgress = time.playback !== 'stop';
const showFinished = time.finished && (time.timerType !== TimerType.Clock || showEndMessage);
const showClock = time.timerType !== TimerType.Clock;
const baseClasses = `stage-timer ${isMirrored ? 'mirror' : ''}`; const baseClasses = `stage-timer ${isMirrored ? 'mirror' : ''}`;
const stageTimer = getTimerByType(time);
let display = formatTimerDisplay(stageTimer);
const stageTimerCharacters = display.replace('/:/g', '').length;
if (isNegative) {
display = `-${display}`;
}
const timerFontSize = 100 / stageTimerCharacters;
const timerClasseNames = `timer ${!isPlaying ? 'timer--paused' : ''} ${showFinished ? 'timer--finished' : ''}`;
return ( return (
<div className={time.finished ? `${baseClasses} stage-timer--finished` : baseClasses} data-testid='timer-view'> <div className={showFinished ? `${baseClasses} stage-timer--finished` : baseClasses} data-testid='timer-view'>
<NavigationMenu /> <NavigationMenu />
<div className={showOverlay ? 'message-overlay message-overlay--active' : 'message-overlay'}> <div className={showOverlay ? 'message-overlay message-overlay--active' : 'message-overlay'}>
<div className='message'>{pres.text}</div> <div className='message'>{pres.text}</div>
</div> </div>
<div className='clock-container'> <div className={`clock-container ${showClock ? '' : 'clock-container--hidden'}`}>
<div className='label'>Time Now</div> <div className='label'>Time Now</div>
<div className='clock'>{clock}</div> <div className='clock'>{clock}</div>
</div> </div>
<div className='timer-container'> <div className='timer-container'>
{time.finished ? ( {showEndMessage ? (
<div className='end-message'> <div className='end-message'>{general.endMessage}</div>
{!general.endMessage ? <TimerDisplay time={time.current} hideZeroHours /> : general.endMessage}
</div>
) : ( ) : (
<TimerDisplay time={normalisedTime} hideZeroHours className={isPlaying ? 'timer' : 'timer--paused'} /> <div
className={timerClasseNames}
style={{
fontSize: `${timerFontSize}vw`,
}}
>
{display}
</div>
)} )}
</div> </div>
@@ -1,35 +0,0 @@
export const event = {
title: '',
subtitle: '',
presenter: '',
note: '',
timeType: 'start-end',
timeStart: 0,
timeEnd: 0,
duration: 0,
isPublic: false,
skip: false,
colour: '',
user0: '',
user1: '',
user2: '',
user3: '',
user4: '',
user5: '',
user6: '',
user7: '',
user8: '',
user9: '',
type: 'event',
revision: 0,
};
export const delay = {
duration: 0,
type: 'delay',
revision: 0,
};
export const block = {
type: 'block',
};
@@ -0,0 +1,38 @@
import { OntimeBlock, OntimeDelay, OntimeEvent, SupportedEvent, TimerType } from 'ontime-types';
export const event: Omit<OntimeEvent, 'id'> = {
title: '',
subtitle: '',
presenter: '',
note: '',
timerBehaviour: 'start-end',
timerType: TimerType.CountDown,
timeStart: 0,
timeEnd: 0,
duration: 0,
isPublic: false,
skip: false,
colour: '',
user0: '',
user1: '',
user2: '',
user3: '',
user4: '',
user5: '',
user6: '',
user7: '',
user8: '',
user9: '',
type: SupportedEvent.Event,
revision: 0,
};
export const delay: Omit<OntimeDelay, 'id'> = {
duration: 0,
type: SupportedEvent.Delay,
revision: 0,
};
export const block: Omit<OntimeBlock, 'id'> = {
type: SupportedEvent.Block,
};
+7 -2
View File
@@ -1,4 +1,4 @@
import { TimerLifeCycle } from 'ontime-types'; import { TimerLifeCycle, TimerType } from 'ontime-types';
import { eventStore } from '../stores/EventStore.js'; import { eventStore } from '../stores/EventStore.js';
import { PlaybackService } from './PlaybackService.js'; import { PlaybackService } from './PlaybackService.js';
@@ -27,6 +27,7 @@ export class TimerService {
secondaryTimer: number | null; secondaryTimer: number | null;
selectedEventId: string | null; selectedEventId: string | null;
duration: number | null; duration: number | null;
timerType: TimerType | null;
}; };
/** /**
@@ -91,6 +92,7 @@ export class TimerService {
secondaryTimer: null, secondaryTimer: null,
selectedEventId: null, selectedEventId: null,
duration: null, duration: null,
timerType: null,
}; };
this.loadedTimerId = null; this.loadedTimerId = null;
this._pausedInterval = 0; this._pausedInterval = 0;
@@ -121,6 +123,7 @@ export class TimerService {
// update relevant information and force update // update relevant information and force update
this.timer.duration = timer.duration; this.timer.duration = timer.duration;
this.timer.timerType = timer.timerType;
// this might not be ideal // this might not be ideal
this.timer.finishedAt = null; this.timer.finishedAt = null;
@@ -138,7 +141,8 @@ export class TimerService {
* @param {number} timer.timeStart * @param {number} timer.timeStart
* @param {number} timer.timeEnd * @param {number} timer.timeEnd
* @param {number} timer.duration * @param {number} timer.duration
* @param {string} timer.timeType * @param {string} timer.timerBehaviour
* @param {string} timer.timerType
* @param {boolean} timer.skip * @param {boolean} timer.skip
*/ */
load(timer) { load(timer) {
@@ -152,6 +156,7 @@ export class TimerService {
this.timer.duration = timer.duration; this.timer.duration = timer.duration;
this.timer.current = timer.duration; this.timer.current = timer.duration;
this.playback = 'armed'; this.playback = 'armed';
this.timer.timerType = timer.timerType;
this._pausedInterval = 0; this._pausedInterval = 0;
this._pausedAt = 0; this._pausedAt = 0;
+2 -1
View File
@@ -310,7 +310,8 @@ export const validateEvent = (eventArgs) => {
presenter: makeString(e.presenter, d.presenter), presenter: makeString(e.presenter, d.presenter),
timeStart: start, timeStart: start,
timeEnd: end, timeEnd: end,
timeType: 'start-end', timerBehaviour: makeString(e.timerBehaviour, d.timerBehaviour),
timerType: makeString(e.timerType, d.timerType),
duration: validateDuration(start, end), duration: validateDuration(start, end),
isPublic: typeof e.isPublic === 'boolean' ? e.isPublic : d.isPublic, isPublic: typeof e.isPublic === 'boolean' ? e.isPublic : d.isPublic,
skip: typeof e.skip === 'boolean' ? e.skip : d.skip, skip: typeof e.skip === 'boolean' ? e.skip : d.skip,
@@ -1,4 +1,4 @@
export enum TimerTypeType { export enum TimerType {
CountDown = 'count-down', CountDown = 'count-down',
CountUp = 'count-up', CountUp = 'count-up',
Clock = 'clock' Clock = 'clock'
@@ -1,3 +1,5 @@
import { TimerType } from '../TimerType.type.js';
export enum SupportedEvent { export enum SupportedEvent {
Event = 'event', Event = 'event',
Delay = 'delay', Delay = 'delay',
@@ -26,7 +28,8 @@ export type OntimeEvent = OntimeBaseEvent & {
subtitle: string; subtitle: string;
presenter: string; presenter: string;
note: string; note: string;
timeType?: string; timerBehaviour: 'start-end',
timerType: TimerType,
timeStart: number; timeStart: number;
timeEnd: number; timeEnd: number;
duration: number; duration: number;
+3 -3
View File
@@ -14,7 +14,7 @@ import { OSCSettings, OscSubscription } from './definitions/core/OscSettings.typ
import { Playback } from './definitions/runtime/Playback.type.js'; import { Playback } from './definitions/runtime/Playback.type.js';
import { Settings } from './definitions/core/Settings.type.js'; import { Settings } from './definitions/core/Settings.type.js';
import { TimerLifeCycle } from './definitions/core/TimerLifecycle.type.js'; import { TimerLifeCycle } from './definitions/core/TimerLifecycle.type.js';
import { TimerTypeType } from './definitions/TimerType.type.js'; import { TimerType } from './definitions/TimerType.type.js';
import { UserFields } from './definitions/core/UserFields.type.js'; import { UserFields } from './definitions/core/UserFields.type.js';
import { ViewSettings } from './definitions/core/Views.type.js'; import { ViewSettings } from './definitions/core/Views.type.js';
@@ -22,10 +22,10 @@ import { ViewSettings } from './definitions/core/Views.type.js';
export type { DatabaseModel }; export type { DatabaseModel };
// ---> Rundown // ---> Rundown
export type { TimerTypeType }; export { TimerType };
export { SupportedEvent };
export type { OntimeBaseEvent, OntimeBlock, OntimeDelay, OntimeEvent }; export type { OntimeBaseEvent, OntimeBlock, OntimeDelay, OntimeEvent };
export type { OntimeRundown, OntimeRundownEntry }; export type { OntimeRundown, OntimeRundownEntry };
export { SupportedEvent };
// ---> Event // ---> Event
export type { EventData }; export type { EventData };