Line data Source code
1 : import * as React from 'react';
2 :
3 : import { SET_SESSION_INPUT, type SessionScripts } from '../scripts/session_scripts.js';
4 : import type { ModifySessionScripts } from '../scripts/session_scripts_registry.js';
5 : import { useSessionExecution } from '../scripts/session_execution_provider.js';
6 : import { deriveSessionInputs, inputConsumerScripts, sessionInputLiteral, type SessionInput } from './session_inputs.js';
7 :
8 1 : const NO_INPUTS: ReadonlySet<string> = new Set();
9 :
10 : /// Apply the value of an input: write its `@param` tag into every script that uses it, then run the scripts that the
11 : /// change affects. Returns the function, the literal of a value of a control, and the inputs whose run is active.
12 1 : export function useApplySessionInput(sessionScripts: SessionScripts, modifySessionScripts: ModifySessionScripts) {
13 1 : const execution = useSessionExecution(sessionScripts.sessionId);
14 1 : const [applied, setApplied] = React.useState<ReadonlySet<string>>(NO_INPUTS);
15 1 : const sessionRef = React.useRef(sessionScripts);
16 1 : sessionRef.current = sessionScripts;
17 1 : const executionRef = React.useRef(execution);
18 1 : executionRef.current = execution;
19 :
20 : // The inputs stay busy while the run that they started runs
21 1 : const busy = execution.busy;
22 1 : const sawBusy = React.useRef(false);
23 1 : React.useEffect(() => {
24 1 : if (busy) sawBusy.current = true;
25 1 : else if (sawBusy.current) {
26 1 : sawBusy.current = false;
27 1 : setApplied(NO_INPUTS);
28 1 : }
29 1 : }, [busy]);
30 :
31 1 : const instance = sessionScripts.instance;
32 1 : const literalOf = React.useCallback((input: SessionInput, value: string) => sessionInputLiteral(instance, input.type, value), [instance]);
33 1 : const apply = React.useCallback((name: string, literal: string) => {
34 0 : const input = deriveSessionInputs(sessionRef.current).find(i => i.name === name);
35 0 : if (input == null) return;
36 0 : setApplied(previous => new Set([...previous, name]));
37 0 : void (async () => {
38 0 : await modifySessionScripts({ type: SET_SESSION_INPUT, value: { name, literal, scriptKeys: inputConsumerScripts(input) } });
39 0 : executionRef.current.start(modifySessionScripts, { inputs: [name] });
40 0 : })();
41 1 : }, [modifySessionScripts]);
42 1 : return { apply, literalOf, busyInputs: busy ? applied : NO_INPUTS };
43 1 : }
|