Fix current block (#1170)

* pass full rundown to loadNow

* remove prevBlock from state

* refactor: simplify load logic (#1174)

* send clock to client on block start to avoid it showing -1 in the client

---------

Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
This commit is contained in:
Alex Christoffer Rasmussen
2024-08-15 16:25:29 +02:00
committed by GitHub
parent 49467c66b7
commit f708dc0bc4
3 changed files with 46 additions and 24 deletions
@@ -69,7 +69,6 @@ class RuntimeService {
@broadcastResult
private checkTimerUpdate({ hasTimerFinished, hasSecondaryTimerFinished }: runtimeState.UpdateResult) {
const newState = runtimeState.getState();
// 1. find if we need to dispatch integrations related to the phase
const timerPhaseChanged = RuntimeService.previousState.timer?.phase !== newState.timer.phase;
if (timerPhaseChanged) {
@@ -664,7 +663,6 @@ function broadcastResult(_target: any, _propertyKey: string, descriptor: Propert
// we do the comparison by explicitly for each property
// to apply custom logic for different datasets
const shouldUpdateClock = getShouldClockUpdate(RuntimeService.previousClockUpdate, state.clock);
const shouldForceTimerUpdate = getForceUpdate(RuntimeService.previousTimerUpdate, state.clock);
const shouldUpdateTimer =
shouldForceTimerUpdate || getShouldTimerUpdate(RuntimeService.previousTimerValue, state.timer.current);
@@ -698,11 +696,16 @@ function broadcastResult(_target: any, _propertyKey: string, descriptor: Propert
updateEventIfChanged('eventNext', state);
updateEventIfChanged('publicEventNext', state);
let syncBlockStartAt = false;
if (!deepEqual(RuntimeService?.previousState.currentBlock, state.currentBlock)) {
eventStore.set('currentBlock', state.currentBlock);
RuntimeService.previousState.currentBlock = { ...state.currentBlock };
syncBlockStartAt = true;
}
const shouldUpdateClock = syncBlockStartAt || getShouldClockUpdate(RuntimeService.previousClockUpdate, state.clock);
if (shouldUpdateClock) {
RuntimeService.previousClockUpdate = state.clock;
eventStore.set('clock', state.clock);
+33 -15
View File
@@ -65,7 +65,6 @@ export type RuntimeState = {
pausedAt: MaybeNumber;
secondaryTarget: MaybeNumber;
};
_prevCurrentBlock: CurrentBlockState;
};
const runtimeState: RuntimeState = {
@@ -86,10 +85,6 @@ const runtimeState: RuntimeState = {
pausedAt: null,
secondaryTarget: null,
},
_prevCurrentBlock: {
block: null,
startedAt: null,
},
};
export function getState(): Readonly<RuntimeState> {
@@ -111,7 +106,6 @@ export function clear() {
runtimeState.publicEventNow = null;
runtimeState.eventNext = null;
runtimeState._prevCurrentBlock = { ...runtimeState.currentBlock };
runtimeState.currentBlock.block = null;
runtimeState.currentBlock.startedAt = null;
@@ -172,7 +166,10 @@ export function load(
rundown: OntimeRundown,
initialData?: Partial<TimerState & RestorePoint>,
): boolean {
// we need to persist the current block state across loads
const prevCurrentBlock = { ...runtimeState.currentBlock };
clear();
runtimeState.currentBlock = prevCurrentBlock;
// filter rundown
const timedEvents = filterTimedEvents(rundown);
@@ -185,6 +182,7 @@ export function load(
// load events in memory along with their data
loadNow(timedEvents, eventIndex);
loadNext(timedEvents, eventIndex);
loadBlock(rundown);
// update state
runtimeState.timer.playback = Playback.Armed;
@@ -215,20 +213,12 @@ export function loadNow(timedEvents: OntimeEvent[], eventIndex: MaybeNumber = ru
// reset the state to indicate there is no selection
runtimeState.runtime.selectedEventIndex = null;
runtimeState.eventNow = null;
runtimeState.currentBlock.block = null;
runtimeState.currentBlock.startedAt = null;
return;
}
const event = timedEvents[eventIndex] as PlayableEvent;
runtimeState.runtime.selectedEventIndex = eventIndex;
runtimeState.eventNow = event;
runtimeState.currentBlock.block = getRelevantBlock(timedEvents, event.id);
// if we are still in the same block keep the startedAt time
if (runtimeState._prevCurrentBlock.block?.id === runtimeState.currentBlock.block?.id) {
runtimeState.currentBlock.startedAt = runtimeState._prevCurrentBlock.startedAt;
}
// check if current is also public
if (event.isPublic) {
@@ -356,7 +346,6 @@ export function updateLoaded(event?: PlayableEvent): string | undefined {
runtimeState.timer.elapsed = null;
runtimeState.timer.expectedFinish = getExpectedFinish(runtimeState);
runtimeState.currentBlock.startedAt = null;
return runtimeState.eventNow.id;
}
@@ -368,6 +357,7 @@ export function updateAll(rundown: OntimeRundown) {
loadNow(timedEvents);
loadNext(timedEvents);
updateLoaded(runtimeState.eventNow ?? undefined);
loadBlock(rundown);
}
export function start(state: RuntimeState = runtimeState): boolean {
@@ -391,6 +381,7 @@ export function start(state: RuntimeState = runtimeState): boolean {
state.timer.startedAt = state.clock;
}
// update block start time
if (state.currentBlock.startedAt === null) {
state.currentBlock.startedAt = state.clock;
}
@@ -582,6 +573,9 @@ export function roll(rundown: OntimeRundown): { eventId: MaybeString; didStart:
runtimeState.timer.startedAt = runtimeState.clock;
// update runtime
if (runtimeState.currentBlock.startedAt === null) {
runtimeState.currentBlock.startedAt = runtimeState.clock;
}
if (!runtimeState.runtime.actualStart) {
runtimeState.runtime.actualStart = runtimeState.clock;
}
@@ -600,12 +594,17 @@ export function roll(rundown: OntimeRundown): { eventId: MaybeString; didStart:
throw new Error('No playable events found');
}
// we need to persist the current block state across loads
const prevCurrentBlock = { ...runtimeState.currentBlock };
clear();
runtimeState.currentBlock = prevCurrentBlock;
const { index, isPending } = loadRoll(timedEvents, runtimeState.clock);
// load events in memory along with their data
loadNow(timedEvents, index);
loadNext(timedEvents, index);
loadBlock(rundown);
// update roll state
runtimeState.timer.playback = Playback.Roll;
@@ -656,3 +655,22 @@ export function roll(rundown: OntimeRundown): { eventId: MaybeString; didStart:
runtimeState.runtime.actualStart = runtimeState.clock;
return { eventId: runtimeState.eventNow.id, didStart: true };
}
function loadBlock(rundown: OntimeRundown) {
if (runtimeState.eventNow === null) {
// we need a loaded event to have a block
runtimeState.currentBlock.block = null;
runtimeState.currentBlock.startedAt = null;
return;
}
const newCurrentBlock = getRelevantBlock(rundown, runtimeState.eventNow.id);
// update time only if the block has changed
if (newCurrentBlock === null || newCurrentBlock.id !== runtimeState.currentBlock.block?.id) {
runtimeState.currentBlock.startedAt = null;
}
// update the block anyway
runtimeState.currentBlock.block = newCurrentBlock === null ? null : { ...newCurrentBlock };
}
@@ -303,20 +303,21 @@ export function getEventWithId(rundown: OntimeRundown, id: string): OntimeRundow
* Gets relevant block element for a given ID
*/
export function getRelevantBlock(rundown: OntimeRundown, currentId: string): OntimeBlock | null {
let inBlock = false;
let foundCurrentEvent = false;
// Iterate backwards through the rundown to find the current event
for (let i = rundown.length - 1; i >= 0; i--) {
const entry = rundown[i];
if (entry.id === currentId) {
//set the flag when the current event is found
inBlock = true;
if (!foundCurrentEvent && entry.id === currentId) {
// set the flag when the current event is found
foundCurrentEvent = true;
continue;
}
//the first block before the current event is the relevant one
if (inBlock && isOntimeBlock(entry)) {
// the first block before the current event is the relevant one
if (foundCurrentEvent && isOntimeBlock(entry)) {
return entry;
}
}
//no blocks exist before current event
// no blocks exist before current event
return null;
}