mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-11 18:33:53 +00:00
feat: many timers (#706)
* wip: create simple timer class * refactor: service to manage extra timers * wip:ui for controlling the extra timer --------- Co-authored-by: arc-alex <ac@omnivox.dk>
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import { SimpleDirection, SimplePlayback, SimpleTimerState } from 'ontime-types';
|
||||
|
||||
export class SimpleTimer {
|
||||
state: SimpleTimerState = {
|
||||
duration: 0,
|
||||
current: 0,
|
||||
playback: SimplePlayback.Stop,
|
||||
direction: SimpleDirection.CountDown,
|
||||
};
|
||||
private startedAt: number | null = null;
|
||||
private pausedAt: number | null = null;
|
||||
|
||||
constructor() {}
|
||||
|
||||
public reset() {
|
||||
this.state = {
|
||||
duration: 0,
|
||||
current: 0,
|
||||
playback: SimplePlayback.Stop,
|
||||
direction: SimpleDirection.CountDown,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the duration of the timer
|
||||
* @param time - time in milliseconds
|
||||
*/
|
||||
public setTime(time: number): SimpleTimerState {
|
||||
this.state.duration = time;
|
||||
this.state.current = time;
|
||||
return this.state;
|
||||
}
|
||||
|
||||
public setDirection(direction: SimpleDirection): SimpleTimerState {
|
||||
this.state.playback = SimplePlayback.Stop;
|
||||
this.state.current = this.state.duration;
|
||||
this.state.direction = direction;
|
||||
return this.state;
|
||||
}
|
||||
|
||||
public start(timeNow: number): SimpleTimerState {
|
||||
if (this.state.playback === SimplePlayback.Pause) {
|
||||
const elapsedSincePause = this.pausedAt - this.startedAt;
|
||||
this.startedAt = timeNow - elapsedSincePause;
|
||||
} else if (this.state.playback === SimplePlayback.Stop) {
|
||||
this.startedAt = timeNow;
|
||||
}
|
||||
this.state.playback = SimplePlayback.Start;
|
||||
return this.update(timeNow);
|
||||
}
|
||||
|
||||
public pause(timeNow: number): SimpleTimerState {
|
||||
if (this.state.playback !== SimplePlayback.Start) return this.state;
|
||||
this.state.playback = SimplePlayback.Pause;
|
||||
this.pausedAt = timeNow;
|
||||
return this.state;
|
||||
}
|
||||
|
||||
public stop(): SimpleTimerState {
|
||||
this.state.playback = SimplePlayback.Stop;
|
||||
this.state.current = this.state.duration;
|
||||
this.startedAt = null;
|
||||
return this.state;
|
||||
}
|
||||
|
||||
public update(timeNow: number): SimpleTimerState {
|
||||
if (this.state.playback === SimplePlayback.Start) {
|
||||
const elapsed = timeNow - this.startedAt;
|
||||
if (this.state.direction === SimpleDirection.CountDown) {
|
||||
this.state.current = this.state.duration - elapsed;
|
||||
} else if (this.state.direction === SimpleDirection.CountUp) {
|
||||
this.state.current = this.state.duration + elapsed;
|
||||
}
|
||||
}
|
||||
|
||||
return this.state;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
import { SimpleDirection, SimplePlayback, SimpleTimerState } from 'ontime-types';
|
||||
|
||||
import { SimpleTimer } from '../SimpleTimer.js';
|
||||
|
||||
describe('SimpleTimer count-down', () => {
|
||||
let timer: SimpleTimer;
|
||||
|
||||
describe('normal timer flow', () => {
|
||||
const initialTime = 1000;
|
||||
timer = new SimpleTimer();
|
||||
|
||||
test('setting the timer duration', () => {
|
||||
const newState = timer.setTime(initialTime);
|
||||
const expected: SimpleTimerState = {
|
||||
duration: initialTime,
|
||||
current: initialTime,
|
||||
direction: SimpleDirection.CountDown,
|
||||
playback: SimplePlayback.Stop,
|
||||
};
|
||||
expect(newState).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
test('setting the timer to play', () => {
|
||||
const newState = timer.start(0);
|
||||
const expected: SimpleTimerState = {
|
||||
duration: initialTime,
|
||||
current: initialTime,
|
||||
direction: SimpleDirection.CountDown,
|
||||
playback: SimplePlayback.Start,
|
||||
};
|
||||
expect(newState).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
test('updating the timer', () => {
|
||||
let newState = timer.update(100);
|
||||
const expected: SimpleTimerState = {
|
||||
duration: initialTime,
|
||||
current: initialTime - 100,
|
||||
direction: SimpleDirection.CountDown,
|
||||
playback: SimplePlayback.Start,
|
||||
};
|
||||
expect(newState).toStrictEqual(expected);
|
||||
|
||||
newState = timer.update(500);
|
||||
expected.current = initialTime - 500;
|
||||
expect(newState).toStrictEqual(expected);
|
||||
|
||||
newState = timer.update(1500);
|
||||
expected.current = initialTime - 1500;
|
||||
expect(newState).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
test('pausing the time doesnt affect the current', () => {
|
||||
const pausedTime = 200;
|
||||
let newState = timer.pause(1500);
|
||||
const expected: SimpleTimerState = {
|
||||
duration: initialTime,
|
||||
current: initialTime - 1500,
|
||||
direction: SimpleDirection.CountDown,
|
||||
playback: SimplePlayback.Pause,
|
||||
};
|
||||
expect(newState).toStrictEqual(expected);
|
||||
|
||||
newState = timer.update(1600);
|
||||
expect(newState).toStrictEqual(expected);
|
||||
|
||||
newState = timer.update(1700);
|
||||
expect(newState).toStrictEqual(expected);
|
||||
|
||||
newState = timer.start(1700);
|
||||
expected.playback = SimplePlayback.Start;
|
||||
expect(newState).toStrictEqual(expected);
|
||||
|
||||
newState = timer.update(1800);
|
||||
(expected.current = initialTime - 1800 + pausedTime), expect(newState).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
test('stopping the timer clears the running data', () => {
|
||||
const newState = timer.stop();
|
||||
const expected: SimpleTimerState = {
|
||||
duration: initialTime,
|
||||
current: initialTime,
|
||||
direction: SimpleDirection.CountDown,
|
||||
playback: SimplePlayback.Stop,
|
||||
};
|
||||
expect(newState).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
test('count-up mode', () => {
|
||||
const initialState = timer.setDirection(SimpleDirection.CountUp);
|
||||
expect(initialState.current).toBe(initialTime);
|
||||
|
||||
let newState = timer.start(0);
|
||||
const expected: SimpleTimerState = {
|
||||
duration: initialTime,
|
||||
current: initialTime,
|
||||
direction: SimpleDirection.CountUp,
|
||||
playback: SimplePlayback.Start,
|
||||
};
|
||||
|
||||
newState = timer.update(100);
|
||||
expected.current = initialTime + 100;
|
||||
expect(newState).toStrictEqual(expected);
|
||||
|
||||
expect(newState).toStrictEqual(expected);
|
||||
|
||||
newState = timer.update(500);
|
||||
expected.current = initialTime + 500;
|
||||
expect(newState).toStrictEqual(expected);
|
||||
|
||||
newState = timer.update(1500);
|
||||
expected.current = initialTime + 1500;
|
||||
expect(newState).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
test('changing direction stops the timer', () => {
|
||||
const newState = timer.setDirection(SimpleDirection.CountDown);
|
||||
const expected: SimpleTimerState = {
|
||||
duration: initialTime,
|
||||
current: initialTime,
|
||||
direction: SimpleDirection.CountDown,
|
||||
playback: SimplePlayback.Stop,
|
||||
};
|
||||
|
||||
expect(newState).toStrictEqual(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user