From 2b568aa7c600556ec1f675fcf02f9b10d999fe54 Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Mon, 3 May 2021 22:02:04 +0200 Subject: [PATCH] feat: negative timers --- .../common/components/countdown/Countdown.jsx | 11 ++-- .../myProgressBar/MyProgressBar.jsx | 5 +- .../src/features/control/PlaybackControl.jsx | 14 ++++- .../control/PlaybackControl.module.css | 51 ++++++++++++++++-- server/classes/Timer.js | 53 +++++++++++-------- 5 files changed, 98 insertions(+), 36 deletions(-) diff --git a/client/src/common/components/countdown/Countdown.jsx b/client/src/common/components/countdown/Countdown.jsx index 8fcb76316..87220671c 100644 --- a/client/src/common/components/countdown/Countdown.jsx +++ b/client/src/common/components/countdown/Countdown.jsx @@ -2,7 +2,7 @@ import { memo, useEffect, useState } from 'react'; import { formatDisplay } from '../../dateConfig'; import styles from './Countdown.module.css'; -const Countdown = ({ time, small, hideZeroHours }) => { +const Countdown = ({ time, small, negative, hideZeroHours }) => { const [clock, setClock] = useState(time); let display = '-- : -- : --'; @@ -12,10 +12,13 @@ const Countdown = ({ time, small, hideZeroHours }) => { // prepare display string if (clock != null && !isNaN(clock)) - display = formatDisplay(clock, hideZeroHours); - + display = formatDisplay(Math.abs(clock), hideZeroHours); + const colour = negative ? '#ff7597' : '#fffffa'; return ( -
+
{display}
); diff --git a/client/src/common/components/myProgressBar/MyProgressBar.jsx b/client/src/common/components/myProgressBar/MyProgressBar.jsx index 6d70be2e4..88b018cbd 100644 --- a/client/src/common/components/myProgressBar/MyProgressBar.jsx +++ b/client/src/common/components/myProgressBar/MyProgressBar.jsx @@ -4,9 +4,8 @@ import styles from './MyProgressBar.module.css'; export default function MyProgressBar(props) { const { now, complete, showElapsed } = props; const percentComplete = showElapsed - ? clamp((100 - (now * 100) / complete + 2), 0, 100) - : clamp((now * 100) / complete - 2, 0, 100) - + ? clamp((100 - (now * 100) / complete), 0, 100) + : clamp((now * 100) / complete, 0, 100) return (
diff --git a/client/src/features/control/PlaybackControl.jsx b/client/src/features/control/PlaybackControl.jsx index 3d74e69f8..9e331ce99 100644 --- a/client/src/features/control/PlaybackControl.jsx +++ b/client/src/features/control/PlaybackControl.jsx @@ -11,6 +11,7 @@ export default function PlaybackControl() { const [playback, setPlayback] = useState(null); const [timer, setTimer] = useState({ clock: null, + running: null, currentSeconds: null, startedAt: null, expectedFinish: null, @@ -90,6 +91,9 @@ export default function PlaybackControl() { const started = stringFromMillis(timer.startedAt, true); const finish = stringFromMillis(timer.expectedFinish, true); + const isNegative = timer.running < 0; + const isDelayed = false; + const isRolling = false; const incrementProps = { size: 'sm', @@ -99,11 +103,19 @@ export default function PlaybackControl() { _focus: { boxShadow: 'none' }, }; + console.log('debug timer', timer.running); return (
+
+
+
+
+
- +
Started at diff --git a/client/src/features/control/PlaybackControl.module.css b/client/src/features/control/PlaybackControl.module.css index 99014c21f..ad5b3d3a0 100644 --- a/client/src/features/control/PlaybackControl.module.css +++ b/client/src/features/control/PlaybackControl.module.css @@ -17,10 +17,10 @@ .timeContainer { display: grid; grid-template-areas: - 'clk clk btn' - 'sta fin btn'; + 'ind clk clk btn' + '... sta fin btn'; grid-template-rows: 1fr auto; - grid-template-columns: 2fr 2fr 22%; + grid-template-columns: 1.5em 2fr 2fr 22%; gap: 5px; justify-items: start; } @@ -29,14 +29,55 @@ grid-area: clk; } +.indicators { + grid-area: ind; + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + justify-content: space-around; +} + +.indRoll, +.indDelay, +.indNegative { + background-color: rgba(0, 0, 0, 0.05); + margin: 0 auto; +} + +.indRoll, +.indDelay { + border-radius: 50%; + width: 0.8em; + height: 0.8em; +} + +.indRollActive { + background-color: #2b6cb0; +} + +.indNegative, +.indNegativeActive { + margin: 0 auto; + width: 90%; + height: 0.3em +} + +.indNegativeActive { + background-color: #ff7597; +} + +.indDelayActive { + background-color: #dd6b20; +} + .btn { grid-area: btn; display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; - justify-content: space-between; - gap: 0.5em; + justify-content: space-around; } .minus { diff --git a/server/classes/Timer.js b/server/classes/Timer.js index c18f18c25..387436c64 100644 --- a/server/classes/Timer.js +++ b/server/classes/Timer.js @@ -9,11 +9,11 @@ class Timer { duration = null; current = null; _finishAt = null; + _finishedAt = null; _startedAt = null; _pausedAt = null; _pausedInterval = null; _pausedTotal = null; - _delays = null; state = 'stop'; constructor() {} @@ -38,7 +38,6 @@ class Timer { this._pausedInterval = 0; } this._pausedTotal = 0; - this._delays = 0; this.update(); } @@ -52,13 +51,15 @@ class Timer { switch (this.state) { case 'start': // update current timer - this.current = Math.max(this._finishAt + this._pausedTotal - now, 0); + this.current = + this._startedAt + this.duration + this._pausedTotal - now; + + if (this.current <= 0 && this._finishedAt == null) + this._finishedAt = now; break; case 'pause': // update paused time - if (this.current > 0) { - this._pausedInterval = now - this._pausedAt; - } + this._pausedInterval = now - this._pausedAt; break; case 'stop': // nothing here yet @@ -86,18 +87,26 @@ class Timer { } _getExpectedFinish() { - if (this._finishAt == null) return null; - return this._finishAt + (this._pausedInterval + this._pausedTotal); + if (this._startedAt == null) return null; + if (this._finishedAt) return this._finishedAt; + + return Math.max( + this._startedAt + + this.duration + + this._pausedInterval + + this._pausedTotal, + this._startedAt + ); } - _resetTimers(resetDelay = true) { + _resetTimers() { this.current = this.duration; this._finishAt = null; + this._finishedAt = null; this._startedAt = null; this._pausedAt = null; this._pausedInterval = null; this._pausedTotal = null; - if (resetDelay) this._delays = null; } // get elapsed time @@ -111,7 +120,8 @@ class Timer { return { clock: this.clock, - currentSeconds: Timer.toSeconds(this.current), + running: Timer.toSeconds(this.current), + currentSeconds: Timer.toSeconds(Math.max(this.current, 0)), durationSeconds: Timer.toSeconds(this.duration), expectedFinish: this._getExpectedFinish(), startedAt: this._startedAt, @@ -129,7 +139,6 @@ class Timer { start() { // do we need to change if (this.state === 'start') return; - else if (this.duration <= 0) return; else if (this._startedAt == null) { // it hasnt started yet const now = this._getCurrentTime(); @@ -156,9 +165,7 @@ class Timer { // do we need to change if (this.state === 'pause') return; - // if there is already paused time (shouldnt) if (this._pausedInterval) { - console.log('TIMER: it was not paused and had pausedInterval'); this._pausedTotal += this._pausedInterval; this._pausedInterval = null; } @@ -177,20 +184,20 @@ class Timer { // clear all timers this._resetTimers(); + // change state this.state = 'stop'; } increment(amount) { - if (amount < 0) { - if (Math.abs(amount) > this.current) { - this._delays -= this.current; - this.current = 0; - this._finishAt = this._getCurrentTime(); - return; - } + this.duration += amount; + + if (amount < 0 && Math.abs(amount) > this.current) { + // if we will make the clock negative + this._finishedAt = this._getCurrentTime(); + } else if (this.current < 0 && this.current + amount > 0) { + // clock will go from negative to positive + this._finishedAt = null; } - this._delays += amount; - this._finishAt += amount; } }