From dd47d2b7e7a7f3d3e6e76d91dff70abd50a28bc1 Mon Sep 17 00:00:00 2001 From: Carlos Valente Date: Sun, 13 Jul 2025 17:32:10 +0200 Subject: [PATCH] refactor: always reload on changes --- .../src/api-data/rundown/rundown.service.ts | 19 +---- .../runtime-service/RuntimeService.ts | 71 +++---------------- apps/server/src/stores/runtimeState.ts | 1 + 3 files changed, 11 insertions(+), 80 deletions(-) diff --git a/apps/server/src/api-data/rundown/rundown.service.ts b/apps/server/src/api-data/rundown/rundown.service.ts index 61f8b234a..7525ce839 100644 --- a/apps/server/src/api-data/rundown/rundown.service.ts +++ b/apps/server/src/api-data/rundown/rundown.service.ts @@ -538,26 +538,11 @@ type NotifyChangesOptions = { /** * Notify services of changes in the rundown - * - * @private - exported for testing */ -export function notifyChanges(rundownMetadata: RundownMetadata, revision: number, options: NotifyChangesOptions) { +function notifyChanges(rundownMetadata: RundownMetadata, revision: number, options: NotifyChangesOptions) { // notify timer service of changed events if (options.timer) { - // all events were deleted - if (rundownMetadata.playableEventOrder.length === 0) { - runtimeService.stop(); - } else { - /** - * Timer can be - * - true: all events changed - * - an array of changed IDs - * - undefined: filtered above, no notification intended - */ - // timer can be true or an array of changed IDs - const affected = Array.isArray(options.timer) ? options.timer : undefined; - runtimeService.notifyOfChangedEvents(affected); - } + runtimeService.notifyOfChangedEvents(rundownMetadata); } // notify external services of changes diff --git a/apps/server/src/services/runtime-service/RuntimeService.ts b/apps/server/src/services/runtime-service/RuntimeService.ts index 93432711c..ae5f1f198 100644 --- a/apps/server/src/services/runtime-service/RuntimeService.ts +++ b/apps/server/src/services/runtime-service/RuntimeService.ts @@ -1,6 +1,5 @@ import { EndAction, - EntryId, isOntimeEvent, isPlayableEvent, LogOrigin, @@ -38,6 +37,7 @@ import { getShouldClockUpdate, getShouldTimerUpdate, } from './rundownService.utils.js'; +import { RundownMetadata } from '../../api-data/rundown/rundown.types.js'; type RuntimeStateEventKeys = keyof Pick; @@ -178,80 +178,25 @@ class RuntimeService { } } - /** - * Checks if a list of IDs is in the current selection - */ - private affectsLoaded(affectedIds: string[]): boolean { - const state = runtimeState.getState(); - const now = state.eventNow?.id; - const next = state.eventNext?.id; - return (now !== undefined && affectedIds.includes(now)) || (next !== undefined && affectedIds.includes(next)); - } - - private isNewNext() { - const { timedEventOrder } = getRundownMetadata(); - - const state = runtimeState.getState(); - const now = state.eventNow?.id; - const next = state.eventNext?.id; - - // check whether the index of now and next are consecutive - const indexNow = timedEventOrder.findIndex((id) => id === now); - const indexNext = timedEventOrder.findIndex((id) => id === next); - - return indexNext - indexNow !== 1; - } - /** * Called when the underlying data has changed, * we check if the change affects the runtime */ - public notifyOfChangedEvents(affectedIds?: EntryId[]) { + public notifyOfChangedEvents(rundownMetadata: RundownMetadata) { const state = runtimeState.getState(); const hasLoadedElements = state.eventNow !== null || state.eventNext !== null; if (!hasLoadedElements) { return; } - // we need to reload in a few scenarios: - // 1. we are not confident that changes do not affect running event (eg. all events where changed) - const safeOption = affectedIds === undefined; - // 2. the edited event is in memory (now or next) running - // behind conditional to avoid doing unnecessary work - const eventInMemory = safeOption ? false : this.affectsLoaded(affectedIds); - // 3. the edited event replaces next event - let isNext = false; - - // if we are not sure, or the event is in memory, we reload - if (safeOption || eventInMemory) { - if (state.eventNow !== null) { - // load stuff again, but keep running if our events still exist - const eventNow = getEntryWithId(state.eventNow.id); - if (!isOntimeEvent(eventNow) || !isPlayableEvent(eventNow)) { - // maybe the event was deleted or the skip state was changed - runtimeState.stop(); - return; - } - const onlyChangedNow = affectedIds?.length === 1 && affectedIds.at(0) === eventNow.id; - - if (onlyChangedNow) { - runtimeState.updateLoaded(eventNow); - } else { - const rundown = getCurrentRundown(); - const metadata = getRundownMetadata(); - runtimeState.updateAll(rundown, metadata); - } - return; - } + // all events were deleted + if (rundownMetadata.playableEventOrder.length === 0) { + runtimeState.stop(); } - // Maybe the event will become the next - isNext = this.isNewNext(); - if (isNext) { - const rundown = getCurrentRundown(); - const metadata = getRundownMetadata(); - runtimeState.loadNext(rundown, metadata); - } + const rundown = getCurrentRundown(); + const metadata = getRundownMetadata(); + runtimeState.updateAll(rundown, metadata); } /** diff --git a/apps/server/src/stores/runtimeState.ts b/apps/server/src/stores/runtimeState.ts index 9262b375c..430c93256 100644 --- a/apps/server/src/stores/runtimeState.ts +++ b/apps/server/src/stores/runtimeState.ts @@ -342,6 +342,7 @@ export function updateAll(rundown: Rundown, metadata: RundownMetadata) { loadNext(rundown, metadata, eventNowIndex >= 0 ? eventNowIndex : undefined); updateLoaded(runtimeState.eventNow ?? undefined); loadBlock(rundown); + loadNextFlag(eventNowIndex, rundown, metadata); } export function start(state: RuntimeState = runtimeState): boolean {