All files / src/components/script ScriptEditor.tsx

0% Statements 0/35
0% Branches 0/12
0% Functions 0/10
0% Lines 0/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109                                                                                                                                                                                                                         
import React, { useContext, useEffect, useMemo, useRef, useState } from "react";
import { useAppSelector } from "store/hooks";
import {
  customEventSelectors,
  scriptEventSelectors,
} from "store/features/entities/entitiesState";
import styled from "styled-components";
import AddButton from "./AddButton";
import ScriptEditorEvent from "./ScriptEditorEvent";
import { ScriptEventAutoFade } from "./ScriptEventAutoFade";
import { calculateAutoFadeEventIdNormalized } from "shared/lib/scripts/eventHelpers";
import { selectScriptEventDefs } from "store/features/scriptEventDefs/scriptEventDefsState";
import { ScriptEditorContext } from "components/script/ScriptEditorContext";
 
interface ScriptEditorProps {
  value: string[];
  showAutoFadeIndicator?: boolean;
}
 
const ScriptEditorWrapper = styled.div`
  position: relative;
`;
 
const ScriptEditor = React.memo(
  ({ value, showAutoFadeIndicator }: ScriptEditorProps) => {
    const context = useContext(ScriptEditorContext);
    const [renderTo, setRenderTo] = useState(0);
    const timerRef = useRef<ReturnType<typeof setTimeout>>();
    const scriptEventsLookup = useAppSelector((state) =>
      scriptEventSelectors.selectEntities(state)
    );
    const customEventsLookup = useAppSelector((state) =>
      customEventSelectors.selectEntities(state)
    );
    const scriptEventDefs = useAppSelector((state) =>
      selectScriptEventDefs(state)
    );
    const autoFadeEventId = useMemo(() => {
      return showAutoFadeIndicator
        ? calculateAutoFadeEventIdNormalized(
            value,
            scriptEventsLookup,
            customEventsLookup,
            scriptEventDefs
          )
        : "";
    }, [
      customEventsLookup,
      scriptEventDefs,
      scriptEventsLookup,
      showAutoFadeIndicator,
      value,
    ]);
 
    // Reset renderTo on script tab change
    useEffect(() => {
      setRenderTo(10);
    }, [context.entityId, context.scriptKey]);
 
    // Load long scripts asynchronously
    useEffect(() => {
      Iif (value.length >= renderTo) {
        timerRef.current = setTimeout(() => {
          setRenderTo(renderTo + 10);
        }, 1);
        return () => {
          Iif (timerRef.current) {
            clearTimeout(timerRef.current);
          }
        };
      }
    }, [renderTo, value.length, context.entityId, context.scriptKey]);
 
    return (
      <ScriptEditorWrapper>
        {value.map(
          (id, index) =>
            index < renderTo && (
              <React.Fragment key={`event_row_${id}_${index}`}>
                {showAutoFadeIndicator && id === autoFadeEventId && (
                  <ScriptEventAutoFade />
                )}
                <ScriptEditorEvent
                  key={`${id}_${index}`}
                  id={id}
                  index={index}
                  parentType={context.entityType}
                  parentId={context.entityId}
                  parentKey={context.scriptKey}
                  entityId={context.entityId}
                />
              </React.Fragment>
            )
        )}
        {showAutoFadeIndicator && autoFadeEventId === "" && (
          <ScriptEventAutoFade />
        )}
        <AddButton
          parentType={context.entityType}
          parentId={context.entityId}
          parentKey={context.scriptKey}
        />
      </ScriptEditorWrapper>
    );
  }
);
 
export default ScriptEditor;