mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-04 15:08:01 +00:00
@@ -12,7 +12,6 @@ export default function RollIconBtn(props) {
|
||||
width={120}
|
||||
_focus={{ boxShadow: 'none' }}
|
||||
{...rest}
|
||||
disabled
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -41,10 +41,7 @@ const Transport = ({ selectedId, playbackControl }) => {
|
||||
<div className={style.playbackContainer}>
|
||||
<PrevIconBtn clickhandler={() => playbackControl('previous')} />
|
||||
<NextIconBtn clickhandler={() => playbackControl('next')} />
|
||||
<UnloadIconBtn
|
||||
clickhandler={() => playbackControl('unload')}
|
||||
disabled={!selectedId}
|
||||
/>
|
||||
<UnloadIconBtn clickhandler={() => playbackControl('unload')} />
|
||||
<ReloadIconButton
|
||||
clickhandler={() => playbackControl('reload')}
|
||||
disabled={!selectedId}
|
||||
|
||||
@@ -90,6 +90,7 @@ export default function PlaybackControl() {
|
||||
<div className={style.mainContainer}>
|
||||
<PlaybackTimer
|
||||
timer={timer}
|
||||
playback={playback}
|
||||
handleIncrement={(amount) => socket.emit('increment-timer', amount)}
|
||||
/>
|
||||
<PlaybackButtons
|
||||
|
||||
@@ -35,18 +35,19 @@
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.indRoll,
|
||||
.indDelay,
|
||||
.indNegative {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.indRoll,
|
||||
.indRollActive,
|
||||
.indDelay {
|
||||
margin: 0 auto;
|
||||
border-radius: 50%;
|
||||
width: 0.8em;
|
||||
height: 0.8em;
|
||||
@@ -60,7 +61,7 @@
|
||||
.indNegativeActive {
|
||||
margin: 0 auto;
|
||||
width: 90%;
|
||||
height: 0.3em
|
||||
height: 0.3em;
|
||||
}
|
||||
|
||||
.indNegativeActive {
|
||||
|
||||
@@ -8,16 +8,18 @@ const areEqual = (prevProps, nextProps) => {
|
||||
return (
|
||||
prevProps.timer.running === nextProps.timer.running &&
|
||||
prevProps.timer.expectedFinish === nextProps.timer.expectedFinish &&
|
||||
prevProps.timer.startedAt === nextProps.timer.startedAt
|
||||
prevProps.timer.startedAt === nextProps.timer.startedAt &&
|
||||
prevProps.playback === nextProps.playback
|
||||
);
|
||||
};
|
||||
|
||||
const PlaybackTimer = ({ timer, handleIncrement }) => {
|
||||
const PlaybackTimer = (props) => {
|
||||
const { timer, playback, handleIncrement } = props;
|
||||
const started = stringFromMillis(timer.startedAt, true);
|
||||
const finish = stringFromMillis(timer.expectedFinish, true);
|
||||
const isNegative = timer.running < 0;
|
||||
const isDelayed = false;
|
||||
const isRolling = false;
|
||||
const isRolling = playback === 'roll';
|
||||
|
||||
const incrementProps = {
|
||||
size: 'sm',
|
||||
@@ -31,7 +33,7 @@ const PlaybackTimer = ({ timer, handleIncrement }) => {
|
||||
<>
|
||||
<div className={style.timeContainer}>
|
||||
<div className={style.indicators}>
|
||||
<div className={style.indRoll} />
|
||||
<div className={isRolling ? style.indRollActive : style.indRoll} />
|
||||
<div
|
||||
className={isNegative ? style.indNegativeActive : style.indNegative}
|
||||
/>
|
||||
@@ -49,16 +51,32 @@ const PlaybackTimer = ({ timer, handleIncrement }) => {
|
||||
<span className={style.time}>{finish}</span>
|
||||
</div>
|
||||
<div className={style.btn}>
|
||||
<Button {...incrementProps} onClick={() => handleIncrement(-1)}>
|
||||
<Button
|
||||
{...incrementProps}
|
||||
disabled={isRolling}
|
||||
onClick={() => handleIncrement(-1)}
|
||||
>
|
||||
-1
|
||||
</Button>
|
||||
<Button {...incrementProps} onClick={() => handleIncrement(1)}>
|
||||
<Button
|
||||
{...incrementProps}
|
||||
disabled={isRolling}
|
||||
onClick={() => handleIncrement(1)}
|
||||
>
|
||||
+1
|
||||
</Button>
|
||||
<Button {...incrementProps} onClick={() => handleIncrement(-5)}>
|
||||
<Button
|
||||
{...incrementProps}
|
||||
disabled={isRolling}
|
||||
onClick={() => handleIncrement(-5)}
|
||||
>
|
||||
-5
|
||||
</Button>
|
||||
<Button {...incrementProps} onClick={() => handleIncrement(5)}>
|
||||
<Button
|
||||
{...incrementProps}
|
||||
disabled={isRolling}
|
||||
onClick={() => handleIncrement(5)}
|
||||
>
|
||||
+5
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -37,7 +37,7 @@ const withSocket = (Component) => {
|
||||
});
|
||||
const [timer, setTimer] = useState({
|
||||
clock: null,
|
||||
currentSeconds: null,
|
||||
running: null,
|
||||
startedAt: null,
|
||||
expectedFinish: null,
|
||||
});
|
||||
@@ -221,7 +221,7 @@ const withSocket = (Component) => {
|
||||
// get clock string
|
||||
const timeManager = {
|
||||
...timer,
|
||||
finished: timer.running <= 0 && timer.startedAt,
|
||||
finished: playback === 'start' && timer.running <= 0 && timer.startedAt,
|
||||
clock: stringFromMillis(timer.clock),
|
||||
playstate: playback,
|
||||
};
|
||||
|
||||
@@ -14,10 +14,9 @@ export default function PresenterView(props) {
|
||||
document.title = 'ontime - Speaker Screen';
|
||||
}, []);
|
||||
|
||||
|
||||
|
||||
const showOverlay = pres.text !== '' && pres.visible;
|
||||
const isPlaying = time.playstate === 'start';
|
||||
const isPlaying = time.playstate !== 'pause';
|
||||
const normalisedTime = Math.max(time.running, 0);
|
||||
|
||||
// motion
|
||||
const titleVariants = {
|
||||
@@ -61,7 +60,7 @@ export default function PresenterView(props) {
|
||||
<div className={style.finished}>TIME UP</div>
|
||||
) : (
|
||||
<div className={isPlaying ? style.countdown : style.countdownPaused}>
|
||||
<Countdown time={time.currentSeconds} hideZeroHours />
|
||||
<Countdown time={normalisedTime} hideZeroHours />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -73,7 +72,7 @@ export default function PresenterView(props) {
|
||||
}
|
||||
>
|
||||
<MyProgressBar
|
||||
now={time.currentSeconds}
|
||||
now={normalisedTime}
|
||||
complete={time.durationSeconds}
|
||||
showElapsed
|
||||
/>
|
||||
|
||||
+167
-28
@@ -109,8 +109,29 @@ class EventTimer extends Timer {
|
||||
|
||||
update() {
|
||||
// if there is nothing selected, no nothing
|
||||
if (this.selectedEventId == null) return;
|
||||
super.update();
|
||||
if (this.selectedEventId == null && this.state !== 'roll') return;
|
||||
|
||||
// only implement roll here
|
||||
if (this.state !== 'roll') {
|
||||
super.update();
|
||||
return;
|
||||
}
|
||||
|
||||
// get current time
|
||||
const now = this._getCurrentTime();
|
||||
this.clock = now;
|
||||
|
||||
if (this.selectedEventId && this.current > 0) {
|
||||
// update timer as usual
|
||||
this.current = this._finishAt - now;
|
||||
} else {
|
||||
// look for event if none is loaded
|
||||
if (this.current <= 0 || this.secondaryTimer <= 0) this.rollLoad();
|
||||
|
||||
// count to next event
|
||||
// TODO: replace with proper counter
|
||||
if (this.secondaryTimer != null) this.secondaryTimer -= 1000;
|
||||
}
|
||||
}
|
||||
|
||||
start() {
|
||||
@@ -140,10 +161,11 @@ class EventTimer extends Timer {
|
||||
else if (payload === 'next') this.next();
|
||||
else if (payload === 'reload') this.reload();
|
||||
else if (payload === 'unload') this.unload();
|
||||
else if (payload === 'roll') this.roll();
|
||||
|
||||
// Not yet implemented
|
||||
// else if (payload === 'roll') this.roll();
|
||||
|
||||
// TODO: Cleanup
|
||||
// here tdo this.broadcastState;
|
||||
// remove broadcast from functions
|
||||
this.broadcastThis('playstate', this.state);
|
||||
this.broadcastThis('selected-id', this.selectedEventId);
|
||||
this.broadcastThis('titles', this.titles);
|
||||
@@ -522,18 +544,12 @@ class EventTimer extends Timer {
|
||||
if (e == null) return;
|
||||
|
||||
// private title is always current
|
||||
this.titles.titleNow = e.title;
|
||||
this.titles.subtitleNow = e.subtitle;
|
||||
this.titles.presenterNow = e.presenter;
|
||||
this.selectedEventId = e.id;
|
||||
|
||||
// check if current is also public
|
||||
if (e.isPublic) {
|
||||
this.titlesPublic.titleNow = e.title;
|
||||
this.titlesPublic.subtitleNow = e.subtitle;
|
||||
this.titlesPublic.presenterNow = e.presenter;
|
||||
this.selectedPublicEventId = e.id;
|
||||
this._loadThisTitles(e, 'now');
|
||||
} else {
|
||||
this._loadThisTitles(e, 'now-private');
|
||||
|
||||
// assume there is no public event
|
||||
this.titlesPublic.titleNow = null;
|
||||
this.titlesPublic.subtitleNow = null;
|
||||
@@ -549,16 +565,77 @@ class EventTimer extends Timer {
|
||||
this._eventlist[i].type === 'event' &&
|
||||
this._eventlist[i].isPublic
|
||||
) {
|
||||
this.titlesPublic.titleNow = this._eventlist[i].title;
|
||||
this.titlesPublic.subtitleNow = this._eventlist[i].subtitle;
|
||||
this.titlesPublic.presenterNow = this._eventlist[i].presenter;
|
||||
this.selectedPublicEventId = this._eventlist[i].id;
|
||||
this._loadThisTitles(this._eventlist[i], 'now-public');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_loadThisTitles(e, type) {
|
||||
if (e == null) return;
|
||||
|
||||
switch (type) {
|
||||
// now, load to both public and private
|
||||
case 'now':
|
||||
// public
|
||||
this.titlesPublic.titleNow = e.title;
|
||||
this.titlesPublic.subtitleNow = e.subtitle;
|
||||
this.titlesPublic.presenterNow = e.presenter;
|
||||
this.selectedPublicEventId = e.id;
|
||||
|
||||
// private
|
||||
this.titles.titleNow = e.title;
|
||||
this.titles.subtitleNow = e.subtitle;
|
||||
this.titles.presenterNow = e.presenter;
|
||||
this.selectedEventId = e.id;
|
||||
|
||||
break;
|
||||
case 'now-public':
|
||||
this.titlesPublic.titleNow = e.title;
|
||||
this.titlesPublic.subtitleNow = e.subtitle;
|
||||
this.titlesPublic.presenterNow = e.presenter;
|
||||
this.selectedPublicEventId = e.id;
|
||||
break;
|
||||
case 'now-private':
|
||||
this.titles.titleNow = e.title;
|
||||
this.titles.subtitleNow = e.subtitle;
|
||||
this.titles.presenterNow = e.presenter;
|
||||
this.selectedEventId = e.id;
|
||||
break;
|
||||
|
||||
// next, load to both public and private
|
||||
case 'next':
|
||||
// public
|
||||
this.titlesPublic.titleNext = e.title;
|
||||
this.titlesPublic.subtitleNext = e.subtitle;
|
||||
this.titlesPublic.presenterNext = e.presenter;
|
||||
this.nextPublicEventId = e.id;
|
||||
|
||||
// private
|
||||
this.titles.titleNext = e.title;
|
||||
this.titles.subtitleNext = e.subtitle;
|
||||
this.titles.presenterNext = e.presenter;
|
||||
this.nextEventId = e.id;
|
||||
break;
|
||||
case 'next-public':
|
||||
this.titlesPublic.titleNext = e.title;
|
||||
this.titlesPublic.subtitleNext = e.subtitle;
|
||||
this.titlesPublic.presenterNext = e.presenter;
|
||||
this.nextPublicEventId = e.id;
|
||||
break;
|
||||
case 'next-private':
|
||||
this.titles.titleNext = e.title;
|
||||
this.titles.subtitleNext = e.subtitle;
|
||||
this.titles.presenterNext = e.presenter;
|
||||
this.nextEventId = e.id;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_loadTitlesNext() {
|
||||
// maybe there is nothing to load
|
||||
if (this.selectedEventIndex == null) return;
|
||||
@@ -583,19 +660,13 @@ class EventTimer extends Timer {
|
||||
if (this._eventlist[i].type === 'event') {
|
||||
// if we have not set private
|
||||
if (!nextPrivate) {
|
||||
this.titles.titleNext = this._eventlist[i].title;
|
||||
this.titles.subtitleNext = this._eventlist[i].subtitle;
|
||||
this.titles.presenterNext = this._eventlist[i].presenter;
|
||||
this.nextEventId = this._eventlist[i].id;
|
||||
this._loadThisTitles(this._eventlist[i], 'next-private');
|
||||
nextPrivate = true;
|
||||
}
|
||||
|
||||
// if event is public
|
||||
if (this._eventlist[i].isPublic) {
|
||||
this.titlesPublic.titleNext = this._eventlist[i].title;
|
||||
this.titlesPublic.subtitleNext = this._eventlist[i].subtitle;
|
||||
this.titlesPublic.presenterNext = this._eventlist[i].presenter;
|
||||
this.nextPublicEventId = this._eventlist[i].id;
|
||||
this._loadThisTitles(this._eventlist[i], 'next-public');
|
||||
nextPublic = true;
|
||||
}
|
||||
}
|
||||
@@ -642,6 +713,7 @@ class EventTimer extends Timer {
|
||||
state = ${this.state}
|
||||
current = ${this.current}
|
||||
duration = ${this.duration}
|
||||
secondaryTimer = ${this.secondaryTimer}
|
||||
|
||||
Events
|
||||
------------------------------
|
||||
@@ -730,10 +802,77 @@ class EventTimer extends Timer {
|
||||
this.broadcastState();
|
||||
}
|
||||
|
||||
rollLoad() {
|
||||
const now = this._getCurrentTime();
|
||||
this._resetTimers(true);
|
||||
this._resetSelection();
|
||||
|
||||
let foundNow = null;
|
||||
let nextIndex = null;
|
||||
let nextStart = null;
|
||||
|
||||
// loop through events, look for where we should be
|
||||
for (const [index, e] of this._eventlist.entries()) {
|
||||
if (!foundNow) {
|
||||
if (e.timeStart <= now && now < e.timeEnd) {
|
||||
// set flag
|
||||
foundNow = true;
|
||||
|
||||
// set timers
|
||||
this._startedAt = e.timeStart;
|
||||
this._finishAt = e.timeEnd;
|
||||
this.duration = e.timeEnd - e.timeStart;
|
||||
this.current = e.timeEnd - now;
|
||||
|
||||
// set selection
|
||||
this.selectedEventId = e.id;
|
||||
this.selectedEventIndex = index;
|
||||
|
||||
// set titles
|
||||
this._loadTitlesNow();
|
||||
|
||||
// skip this entry for next
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// check how far the start is from now
|
||||
let wait = e.timeStart - now;
|
||||
if (wait > 0) {
|
||||
if (nextStart == null || wait < nextStart) {
|
||||
nextStart = wait;
|
||||
nextIndex = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// nothing to play next, unload
|
||||
if (!foundNow && !nextIndex) {
|
||||
this.unload();
|
||||
return;
|
||||
}
|
||||
|
||||
if (nextIndex) {
|
||||
// load titles
|
||||
this._loadThisTitles(nextIndex, 'next');
|
||||
|
||||
if (!foundNow) {
|
||||
// timer counts to nextStart
|
||||
this.secondaryTimer = nextStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
roll() {
|
||||
console.log('roll: not yet implemented');
|
||||
return false;
|
||||
// do we need to change
|
||||
if (this.state === 'roll') return;
|
||||
|
||||
// load into event
|
||||
this.rollLoad();
|
||||
|
||||
// set state
|
||||
this.state = 'roll';
|
||||
|
||||
this.broadcastState();
|
||||
}
|
||||
|
||||
previous() {
|
||||
|
||||
@@ -8,6 +8,7 @@ class Timer {
|
||||
clock = null;
|
||||
duration = null;
|
||||
current = null;
|
||||
secondaryTimer = null;
|
||||
_finishAt = null;
|
||||
_finishedAt = null;
|
||||
_startedAt = null;
|
||||
@@ -113,8 +114,10 @@ class Timer {
|
||||
);
|
||||
}
|
||||
|
||||
_resetTimers() {
|
||||
_resetTimers(total = false) {
|
||||
if (total) this.duration = null;
|
||||
this.current = this.duration;
|
||||
this.secondaryTimer = null;
|
||||
this._finishAt = null;
|
||||
this._finishedAt = null;
|
||||
this._startedAt = null;
|
||||
@@ -135,7 +138,7 @@ class Timer {
|
||||
return {
|
||||
clock: this.clock,
|
||||
running: Timer.toSeconds(this.current),
|
||||
currentSeconds: Timer.toSeconds(Math.max(this.current, 0)),
|
||||
secondary: Timer.toSeconds(this.secondaryTimer),
|
||||
durationSeconds: Timer.toSeconds(this.duration),
|
||||
expectedFinish: this._getExpectedFinish(),
|
||||
startedAt: this._startedAt,
|
||||
|
||||
Reference in New Issue
Block a user