function keyHandle()

in packages/ketcher-react/src/script/ui/state/hotkeys.ts [99:216]


function keyHandle(dispatch, getState, hotKeys, event) {
  const state = getState();

  if (state.modal || selectIsAbbreviationLookupOpen(state)) return;

  const { editor } = state;
  const { render } = editor;
  const actionState = state.actionState;
  const actionTool = actionState.activeTool;

  const key = keyNorm(event);

  let group: any = null;

  const hoveredItem = getHoveredItem(render.ctab);

  if (key && key.length === 1 && !hoveredItem) {
    const currentlyPressedKeys = selectAbbreviationLookupValue(state);
    const isShortcutKey = shortcutKeys.includes(key?.toLowerCase());
    const isTheSameKey = key === currentlyPressedKeys;
    const isAbbreviationLookupShown =
      (!isTheSameKey || !isShortcutKey) && currentlyPressedKeys;
    if (isAbbreviationLookupShown) {
      dispatch(showAbbreviationLookup(event.key));
      clearTimeout(abbreviationLookupTimeoutId);
      abbreviationLookupTimeoutId = undefined;

      const resetAction = SettingsManager.getSettings().selectionTool;
      dispatch(onAction(resetAction));

      event.preventDefault();
      return;
    } else {
      abbreviationLookupTimeoutId = window.setTimeout(() => {
        dispatch(closeAbbreviationLookup());
        abbreviationLookupTimeoutId = undefined;
      }, ABBREVIATION_LOOKUP_TYPING_TIMEOUT);

      dispatch(initAbbreviationLookup(event.key));
    }
  }

  if (key && key.length === 1 && key.match('/')) {
    const hotkeyDialogTypes = {
      atoms: actions['atom-props'].action,
      bonds: actions['bond-props'].action,
    };

    if (!hoveredItem) {
      return;
    }
    const dialogType = Object.keys(hoveredItem)[0];

    if (Object.hasOwn(hotkeyDialogTypes, dialogType)) {
      handleHotkeyOverItem({
        hoveredItem,
        newAction: hotkeyDialogTypes[dialogType],
        editor,
        dispatch,
      });
    }

    event.preventDefault();
  } else if (editor.rotateController.isRotating && key === 'Escape') {
    editor.rotateController.revert();
  } else if ((group = keyNorm.lookup(hotKeys, event)) !== undefined) {
    const index = checkGroupOnTool(group, actionTool); // index currentTool in group || -1
    const groupLength = group !== null ? group.length : 1;
    const newIndex = (index + 1) % groupLength;

    const actName = group[newIndex];
    if (actionState[actName] && actionState[actName].disabled === true) {
      event.preventDefault();
      return;
    }
    // Removing from what should be saved - structure, which was added to paste tool,
    // but not yet rendered on canvas
    removeNotRenderedStruct(actionTool, group, dispatch);

    if (clipArea.actions.indexOf(actName) === -1) {
      let newAction = ['zoom-in', 'zoom-out'].includes(actName)
        ? actions[actName].action()
        : actions[actName].action;
      const hoveredItem = getHoveredItem(render.ctab);
      // check if atom is currently hovered over
      // in this case we do not want to activate the corresponding tool
      // and just insert the atom directly
      if (
        hoveredItem &&
        newAction.tool !== 'select' &&
        newAction.dialog !== 'templates'
      ) {
        newAction = getCurrentAction(group[index]) || newAction;
        handleHotkeyOverItem({
          hoveredItem,
          newAction,
          editor,
          dispatch,
        });
      } else {
        if (newAction.tool === 'select') {
          if (key === 'Escape') {
            newAction = SettingsManager.getSettings().selectionTool;
          } else if (index === -1) {
            newAction = {};
          }
        }
        dispatch(onAction(newAction));
      }

      event.preventDefault();
    } else if (isIE) {
      clipArea.exec(event);
    }
  } else if (isArrowKey(event.key)) {
    moveSelectedItems(editor, event.key, event.shiftKey);
  }
}