repond-events
Version:
events for repond
106 lines (90 loc) • 4.13 kB
text/typescript
import { breakableForEach, forEach } from "chootils/dist/loops";
import { ItemState, getItemWillExist, getState, makeEffects, removeItem, setState, whenSettingStates } from "repond";
import { getActiveEventIds } from "../internal";
import { repondEventsMeta } from "../meta";
export const chainEffects = makeEffects((then) => ({
whenLiveEventIdsChange: then(
(chainId) => {
const nowChainState = getState("chains", chainId);
if (!nowChainState) return;
const { liveEventIds: firstLiveEventIds, canAutoActivate } = nowChainState;
const isSubChain = getItemWillExist("liveEvents", chainId);
// Remove the chain if there's no liveEventIds left in the chain
if (firstLiveEventIds.length === 0) {
removeItem("chains", chainId);
// if there's a getEventValue that was waiting for a returnValue in the chain, but the chain ended,
// return null for the chain
repondEventsMeta.resolveValueMap[chainId]?.(undefined);
}
// Check which events should be active
whenSettingStates(() => {
const chainState = getState("chains", chainId);
if (!chainState) return; // NOTE maybe warn here
const { liveEventIds } = chainState;
let idsToActivate: string[] = getActiveEventIds(liveEventIds ?? []);
// NOTE these are only for reference! we don't use this to set state directly
let newLiveEventsState: Record<string, Partial<ItemState<"liveEvents">>> = {};
let newChainsState: Record<string, Partial<ItemState<"chains">>> = {};
if (isSubChain) {
let foundNonAddEvent = false;
breakableForEach(idsToActivate, (id) => {
const loopedRunMode = getState("events", id)?.nowRunMode;
if (!loopedRunMode) {
console.log("no loopedRunMode: id", id);
}
if (loopedRunMode && loopedRunMode !== "add") {
foundNonAddEvent = true;
return true; // break
}
});
if (foundNonAddEvent) {
newChainsState[chainId] = { canAutoActivate: true };
setState("chains.canAutoActivate", true, chainId);
}
}
// Return if the chain can't or wont be able to auto activate
if (!canAutoActivate && !newChainsState[chainId]?.canAutoActivate) {
return;
}
if (!liveEventIds?.length) {
if (isSubChain) {
// If it's a sub chain, finish the parent liveEvent
// return { liveEvents: { [chainId]: { goalEndTime: 0 } } };
setState("liveEvents.goalEndTime", 0, chainId);
// Set state then exit
return;
}
// Only exit
return;
}
breakableForEach(idsToActivate, (id) => {
const liveEventState = getState("liveEvents", id);
if (!liveEventState) return;
const { runModeOptionsWhenReady } = liveEventState;
if (runModeOptionsWhenReady) {
const { runMode, runBy } = runModeOptionsWhenReady;
newLiveEventsState[id] = { nowRunMode: runMode, runBy: runBy ?? null, runModeOptionsWhenReady: null };
setState("liveEvents.nowRunMode", runMode, id);
setState("liveEvents.runBy", runBy ?? null, id);
setState("liveEvents.runModeOptionsWhenReady", null, id);
} else {
newLiveEventsState[id] = { nowRunMode: "start" };
setState("liveEvents.nowRunMode", "start", id);
}
});
// Loop through all the new partial events, if any of them have a subChain, set the chain to canAutoActivate
forEach(Object.keys(newLiveEventsState), (liveId) => {
const loopedEventHasSubChain = getItemWillExist("chains", liveId);
if (loopedEventHasSubChain) {
newChainsState[liveId] = { canAutoActivate: true };
setState("chains.canAutoActivate", true, liveId);
}
});
});
},
{
changes: ["chains.liveEventIds", "chains.canAutoActivate"],
step: "eventUpdates",
}
),
}));