repond-events
Version:
events for repond
202 lines (201 loc) • 9.51 kB
JavaScript
import { forEach } from "chootils/dist/loops";
import { getItemIds, onNextTick, whenSettingStates } from "repond";
import { _addEvent, _addEvents, _makeLiveIdFromEventBlock, _setStatesToRunEventsInMode, eventBlockBaseToEventBlock, getChainIdFromLiveEventId, getLiveEventsIdsUpToLiveEventId, getLiveIdsForGroup, makeNewChainId, } from "./internal";
import { repondEventsMeta } from "./meta";
// Returns an event block tuple, useful to get a typed event with auto-completion
// meant to use with runEvents like runEvents([run("group", "name", params), run("group", "name", params)])
export function todo(groupOrEmoji, name, ...args) {
const group = groupOrEmoji in repondEventsMeta.emojiKeys
? repondEventsMeta.emojiKeys[groupOrEmoji]
: groupOrEmoji;
// ...params: OptionalIfUndefinableSpreadType<
// TypeOrUndefinedIfAllOptional<EventParams<T_Group, T_Name, T_GenericParamA>>
// >,
// options?: EventBlockOptions
// Destructure args to get params and options
let params = args[0]; // This would be your number or undefined
let options = args[1]; // This would be your EventBlockOptions or undefined
// const eventTuple: EventBlockTuple = [group, name, params ?? {}, options] as EventBlockTuple;
const eventBlock = { group, name, params: params ?? {}, options };
return eventBlock;
}
// ---------------------------------------------
// Events and chains
// NOTE most of the helper functions
// - Run inside set state - to read the latest state if setStates were run before this
// - Run inside onNextTick - to run after the current setStates and effects, to run at the start of the next frame
export function runEvent(groupOrEmoji, name, ...args) {
const group = groupOrEmoji in repondEventsMeta.emojiKeys
? repondEventsMeta.emojiKeys[groupOrEmoji]
: groupOrEmoji;
// Destructure args to get params and options
let params = args[0]; // This would be your number or undefined
let options = args[1]; // This would be your EventBlockOptions or undefined
const eventBlock = eventBlockBaseToEventBlock({ group, name, params: params ?? {} }, options);
// generate the same chainId that would be generated if the event was added, but it's needed to get the liveId
// NOTE in _addEvents, a liveId given means its the parent liveId for subEvents, meaning the chainId will be the same as the parent liveId,
// but since this function only adds one event, the chainId will be different from the liveId
const chainId = options?.chainId ?? repondEventsMeta.defaultChainId ?? makeNewChainId();
eventBlock.options.chainId = chainId;
const liveId = options?.liveId ?? _makeLiveIdFromEventBlock(eventBlock);
const realLiveId = _addEvent({ group, name, params: params ?? {} }, { ...options, liveId, chainId });
return realLiveId;
}
export function runPriorityEvent(group, name, params, options) {
// NOTE _addEvent runs _addEvents which has onNextTick inside
const chainId = _addEvent({ group, name, params: params ?? {} }, { hasPriority: true, ...options });
return chainId;
}
export function runEvents(eventsToRun, options) {
// NOTE _addEvents has onNextTick inside
// NOTE adding a liveId will make the chain a subChain of the liveEvent
// const chainId = _addEvents(eventTuplesToEventBlocks(eventsToRun), { ...options });
const chainId = _addEvents(eventsToRun, { ...options });
return chainId;
}
export function addSubEvents(liveId, eventsToRun, options) {
runEvents(eventsToRun, { liveId, ...options });
}
export function runPriorityEvents(eventsToRun, options) {
// NOTE runEvents runs _addEvents which has onNextTick inside
return runEvents(eventsToRun, { hasPriority: true, ...options });
}
export function eventDo(runMode, liveId, runOptions) {
onNextTick(() => whenSettingStates(() => _setStatesToRunEventsInMode({ runMode, targetLiveIds: [liveId], runOptions })));
}
export function chainDo(runMode, chainId, runOptions) {
onNextTick(() => whenSettingStates(() => _setStatesToRunEventsInMode({ runMode, chainId, runOptions })));
}
export function chainWithEventDo(runMode, liveId, runOptions) {
whenSettingStates(() => {
const chainId = getChainIdFromLiveEventId(liveId);
// `no chain found for ${liveId}`
if (!chainId)
return;
_setStatesToRunEventsInMode({ runMode, chainId, runOptions });
});
}
export function allGroupEventsDo(groupName, runMode, runOptions) {
onNextTick(() => {
whenSettingStates(() => {
const targetLiveIds = getLiveIdsForGroup(groupName);
_setStatesToRunEventsInMode({ runMode, targetLiveIds, runOptions });
});
});
}
export function doForAllBeforeEvent(runMode, liveId, runOptions) {
onNextTick(() => {
whenSettingStates(() => {
const targetLiveIds = getLiveEventsIdsUpToLiveEventId(liveId);
_setStatesToRunEventsInMode({ runMode, targetLiveIds, runOptions });
});
});
}
export function skipToEvent(liveId, runOptions) {
doForAllBeforeEvent("skip", liveId, runOptions);
}
export function cancelUpToEvent(liveId, runOptions) {
doForAllBeforeEvent("cancel", liveId, runOptions);
}
export function allEventsDo(runMode, runOptions) {
whenSettingStates(() => {
const targetLiveIds = getItemIds("liveEvents");
_setStatesToRunEventsInMode({ runMode, targetLiveIds, runOptions });
});
}
// ---------------------------------------------
export function cancelFastChain(chainId) {
// set isCancelled to true,
// and while it can’t find another child in meta,
// keep setting children to isCanceled
const fastChainMeta = repondEventsMeta.fastChain.nowFastChainsInfoMap[chainId];
if (!fastChainMeta)
return;
fastChainMeta.isCanceled = true;
let nextChildChainId = fastChainMeta.nowChildFastChainId;
while (nextChildChainId) {
const nextChildMeta = repondEventsMeta.fastChain.nowFastChainsInfoMap[nextChildChainId];
if (!nextChildMeta)
break;
nextChildMeta.isCanceled = true;
nextChildChainId = nextChildMeta.nowChildFastChainId;
}
}
// ---------------------------------------------
// Make Events
function makeEventType(event) {
return event;
}
export function makeEventTypes(eventsToAdd) {
return eventsToAdd({ event: makeEventType });
}
export function initEventTypeGroups(groups, options) {
repondEventsMeta.defaultElapsedTimePath = options?.defaultElapsedTimePath ?? null;
repondEventsMeta.defaultChainId = options?.defaultChainId ?? null;
repondEventsMeta.emojiKeys = options?.emojiKeys ?? {};
const transformedGroups = {};
Object.entries(groups).forEach(([key, value]) => {
// Remove "Events" from the end of the key, if present
const newKey = key.replace(/Events$/, "");
transformedGroups[newKey] = value;
});
const groupNames = Object.keys(transformedGroups);
// loop through the groups and rename the effects
forEach(groupNames, (groupName) => {
const theGroup = transformedGroups[groupName];
const eventTypeNames = Object.keys(theGroup);
forEach(eventTypeNames, (eventTypeName) => {
const theEventType = theGroup[eventTypeName];
theEventType.id = `${groupName}_${eventTypeName}`;
});
});
// Store the transformed groups
repondEventsMeta.allEventTypeGroups = transformedGroups;
return groups;
}
// ---------------------------------------------
// Make Values
function makeValueType(value) {
return value;
}
export function makeValueTypes(valuesToAdd) {
return valuesToAdd({ value: makeValueType });
}
export function initValueTypeGroups(groups, options) {
repondEventsMeta.valueEmojiKeys = options?.emojiKeys ?? {};
const transformedGroups = {};
Object.entries(groups).forEach(([key, value]) => {
// Remove "Values" from the end of the key, if present
const newKey = key.replace(/Values$/, "");
transformedGroups[newKey] = value;
});
const groupNames = Object.keys(transformedGroups);
// loop through the groups and rename the effects
forEach(groupNames, (groupName) => {
const theGroup = transformedGroups[groupName];
const valueTypeNames = Object.keys(theGroup);
forEach(valueTypeNames, (valueTypeName) => {
const theValueType = theGroup[valueTypeName];
theValueType.id = `${groupName}_${valueTypeName}`;
});
});
// Store the transformed groups
repondEventsMeta.allValueTypeGroups = transformedGroups;
return groups;
}
// Returns an event block tuple, useful to get a typed event with auto-completion
// meant to use with runEvents like runEvents([run("group", "name", params), run("group", "name", params)])
export function makeValue(groupOrEmoji, name, ...args) {
const group = groupOrEmoji in repondEventsMeta.valueEmojiKeys
? repondEventsMeta.emojiKeys[groupOrEmoji]
: groupOrEmoji;
// ...params: OptionalIfUndefinableSpreadType<
// TypeOrUndefinedIfAllOptional<EventParams<T_Group, T_Name, T_GenericParamA>>
// >,
// options?: EventBlockOptions
// Destructure args to get params and options
let params = args[0];
let options = args[1]; // This would be your EventBlockOptions or undefined
const valueBlock = { group, name, params: params || {}, options: options ?? {}, type: "value" };
return valueBlock;
}