refactor: partial state updates (#780)

* refactor: partial state updates

* refactor: less calls to restore

* refactor: add error stack trace to log
This commit is contained in:
Carlos Valente
2024-02-19 21:31:27 +01:00
committed by GitHub
parent c890251dad
commit 7ff75835ff
22 changed files with 523 additions and 361 deletions
@@ -3,11 +3,11 @@ import {
OntimeBlock,
OntimeDelay,
OntimeEvent,
OntimeRundown,
OntimeRundownEntry,
isOntimeBlock,
isOntimeDelay,
isOntimeEvent,
OntimeRundown,
} from 'ontime-types';
import { getCueCandidate } from 'ontime-utils';
@@ -19,6 +19,7 @@ import { updateRundownData } from '../../stores/runtimeState.js';
import { runtimeService } from '../runtime-service/RuntimeService.js';
import * as cache from './rundownCache.js';
import { getPlayableEvents } from './rundownUtils.js';
function generateEvent(eventData: Partial<OntimeEvent> | Partial<OntimeDelay> | Partial<OntimeBlock>) {
// we discard any UI provided events and add our own
@@ -44,7 +45,9 @@ function generateEvent(eventData: Partial<OntimeEvent> | Partial<OntimeDelay> |
* @param {object} eventData
* @return {OntimeRundownEntry}
*/
export async function addEvent(eventData: Partial<OntimeEvent> | Partial<OntimeDelay> | Partial<OntimeBlock>) {
export async function addEvent(
eventData: Partial<OntimeEvent> | Partial<OntimeDelay> | Partial<OntimeBlock>,
): Promise<OntimeRundownEntry> {
// if the user didnt provide an index, we add the event to start
let atIndex = 0;
if (eventData?.after !== undefined) {
@@ -65,7 +68,7 @@ export async function addEvent(eventData: Partial<OntimeEvent> | Partial<OntimeD
notifyChanges({ timer: [newEvent.id], external: true });
// notify runtime that rundown size has changed
updateChangeNumEvents();
updateRuntimeOnChange();
return newEvent;
}
@@ -73,7 +76,6 @@ export async function addEvent(eventData: Partial<OntimeEvent> | Partial<OntimeD
/**
* deletes event by its ID
* @param eventId
* @returns {Promise<void>}
*/
export async function deleteEvent(eventId: string) {
const scopedMutation = cache.mutateCache(cache.remove);
@@ -82,12 +84,11 @@ export async function deleteEvent(eventId: string) {
notifyChanges({ timer: [eventId], external: true });
// notify event loader that rundown size has changed
updateChangeNumEvents();
updateRuntimeOnChange();
}
/**
* deletes all events in database
* @returns {Promise<void>}
*/
export async function deleteAllEvents() {
const scopedMutation = cache.mutateCache(cache.removeAll);
@@ -97,6 +98,10 @@ export async function deleteAllEvents() {
notifyChanges({ external: true });
}
/**
* Apply patch to an element in rundown
* @param patch
*/
export async function editEvent(patch: Partial<OntimeEvent> | Partial<OntimeBlock> | Partial<OntimeDelay>) {
if (isOntimeEvent(patch) && patch?.cue === '') {
throw new Error('Cue value invalid');
@@ -111,6 +116,11 @@ export async function editEvent(patch: Partial<OntimeEvent> | Partial<OntimeBloc
return newEvent;
}
/**
* Applies a patch to several elements in a rundown
* @param ids
* @param data
*/
export async function batchEditEvents(ids: string[], data: Partial<OntimeEvent>) {
const scopedMutation = cache.mutateCache(cache.batchEdit);
await scopedMutation({ patch: data, eventIds: ids });
@@ -123,7 +133,6 @@ export async function batchEditEvents(ids: string[], data: Partial<OntimeEvent>)
* @param {string} eventId - ID of event from, for sanity check
* @param {number} from - index of event from
* @param {number} to - index of event to
* @returns {Promise<void>}
*/
export async function reorderEvent(eventId: string, from: number, to: number) {
const scopedMutation = cache.mutateCache(cache.reorder);
@@ -158,7 +167,7 @@ export async function swapEvents(from: string, to: string) {
* Forces update in the store
* Called when we make changes to the rundown object
*/
function updateChangeNumEvents() {
function updateRuntimeOnChange() {
updateRundownData(getPlayableEvents());
}
@@ -167,12 +176,13 @@ function updateChangeNumEvents() {
*/
export function notifyChanges(options: { timer?: boolean | string[]; external?: boolean }) {
if (options.timer) {
const playableEvents = getPlayableEvents();
// notify timer service of changed events
// timer can be true or an array of changed IDs
if (Array.isArray(options.timer)) {
runtimeService.update(options.timer);
runtimeService.maybeUpdate(playableEvents, options.timer);
}
runtimeService.update();
runtimeService.maybeUpdate(playableEvents);
}
if (options.external) {
@@ -181,115 +191,11 @@ export function notifyChanges(options: { timer?: boolean | string[]; external?:
}
}
/**
* returns entire unfiltered rundown
* @return {array}
*/
export function getRundown(): OntimeRundown {
return cache.getPersistedRundown();
}
/**
* returns all events of type OntimeEvent
* @return {array}
*/
export function getTimedEvents(): OntimeEvent[] {
return getRundown().filter((event) => isOntimeEvent(event)) as OntimeEvent[];
}
/**
* returns all events that can be loaded
* @return {array}
*/
export function getPlayableEvents(): OntimeEvent[] {
return getRundown().filter((event) => isOntimeEvent(event) && !event.skip) as OntimeEvent[];
}
/**
* returns number of events that can be loaded
* @return {number}
*/
export function getNumEvents(): number {
return getPlayableEvents().length;
}
/**
* returns an event given its index after filtering for OntimeEvents
* @param {number} eventIndex
* @return {OntimeEvent | undefined}
*/
export function getEventAtIndex(eventIndex: number): OntimeEvent | undefined {
const timedEvents = getTimedEvents();
return timedEvents.at(eventIndex);
}
/**
* returns first event that matches a given ID
* @param {string} eventId
* @return {object | undefined}
*/
export function getEventWithId(eventId: string): OntimeEvent | undefined {
const timedEvents = getTimedEvents();
return timedEvents.find((event) => event.id === eventId);
}
/**
* returns first event that matches a given cue
* @param {string} cue
* @return {object | undefined}
*/
export function getEventWithCue(cue: string): OntimeEvent | undefined {
const timedEvents = getTimedEvents();
return timedEvents.find((event) => event.cue.toLowerCase() === cue.toLowerCase());
}
/**
* finds the previous event
* @return {object | undefined}
*/
export function findPrevious(currentEventId?: string): OntimeEvent | null {
const timedEvents = getPlayableEvents();
if (!timedEvents || !timedEvents.length) {
return null;
}
// if there is no event running, go to first
if (!currentEventId) {
return timedEvents.at(0) ?? null;
}
const currentIndex = timedEvents.findIndex((event) => event.id === currentEventId);
const newIndex = Math.max(currentIndex - 1, 0);
const previousEvent = timedEvents.at(newIndex) ?? null;
return previousEvent;
}
/**
* finds the next event
* @return {object | undefined}
*/
export function findNext(currentEventId?: string): OntimeEvent | null {
const timedEvents = getPlayableEvents();
if (!timedEvents || !timedEvents.length) {
return null;
}
// if there is no event running, go to first
if (!currentEventId) {
return timedEvents.at(0) ?? null;
}
const currentIndex = timedEvents.findIndex((event) => event.id === currentEventId);
const newIndex = (currentIndex + 1) % timedEvents.length;
const nextEvent = timedEvents.at(newIndex);
return nextEvent ?? null;
}
/**
* Overrides the rundown with the given
* @param rundown
*/
export async function setRundown(rundown: OntimeRundown) {
cache.init(rundown);
await cache.init(rundown);
notifyChanges({ timer: true });
}