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