diff --git a/src/components/FileMachineProvider.tsx b/src/components/FileMachineProvider.tsx index 5ca34a7da48..63607ece114 100644 --- a/src/components/FileMachineProvider.tsx +++ b/src/components/FileMachineProvider.tsx @@ -433,13 +433,7 @@ export const FileMachineProvider = ({ // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: blanket-ignored fix me! }, [location]) - const cb = modelingMenuCallbackMostActions( - settings, - navigate, - filePath, - project, - token - ) + const cb = modelingMenuCallbackMostActions(settings, navigate, filePath) useMenuListener(cb) const kclCommandMemo = useMemo(() => { diff --git a/src/components/ModelingPageProvider.tsx b/src/components/ModelingPageProvider.tsx index 115ce217604..93752c70201 100644 --- a/src/components/ModelingPageProvider.tsx +++ b/src/components/ModelingPageProvider.tsx @@ -107,13 +107,7 @@ export const ModelingPageProvider = ({ // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: blanket-ignored fix me! }, [location]) - const cb = modelingMenuCallbackMostActions( - settings, - navigate, - filePath, - project, - token - ) + const cb = modelingMenuCallbackMostActions(settings, navigate, filePath) useMenuListener(cb) const kclCommandMemo = useMemo(() => { diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 912fbb969cd..f703c098d66 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -38,6 +38,19 @@ export async function refreshPage(method = 'UI button') { window?.location.reload() } +export function activeFocusIsInput() { + return document.activeElement && isInputElement(document.activeElement) +} + +function isInputElement( + element: EventTarget +): element is HTMLInputElement | HTMLTextAreaElement { + return ( + element instanceof HTMLInputElement || + element instanceof HTMLTextAreaElement + ) +} + /** * Get all labels for a keyword call expression. */ diff --git a/src/menu/register.ts b/src/menu/register.ts index 448d573a96c..7751147cfd1 100644 --- a/src/menu/register.ts +++ b/src/menu/register.ts @@ -1,10 +1,9 @@ import { AxisNames } from '@src/lib/constants' import { PATHS } from '@src/lib/paths' -import type { Project } from '@src/lib/project' import type { SettingsType } from '@src/lib/settings/initialSettings' import { engineCommandManager, sceneInfra } from '@src/lib/singletons' import { reportRejection } from '@src/lib/trap' -import { uuidv4 } from '@src/lib/utils' +import { activeFocusIsInput, uuidv4 } from '@src/lib/utils' import { authActor, commandBarActor, @@ -17,9 +16,7 @@ import type { NavigateFunction } from 'react-router-dom' export function modelingMenuCallbackMostActions( settings: SettingsType, navigate: NavigateFunction, - filePath: string, - project: Project | undefined, - token: string | undefined + filePath: string ) { // Menu listeners const cb = (data: WebContentSendPayload) => { @@ -124,9 +121,19 @@ export function modelingMenuCallbackMostActions( data: { name: 'format-code', groupId: 'code' }, }) } else if (data.menuLabel === 'Edit.Undo') { - editorManager.undo() + if (activeFocusIsInput()) { + document.execCommand('undo') + // Cleaner, but can't import 'electron' to this file: + // webContents.getFocusedWebContents()?.undo() + } else { + editorManager.undo() + } } else if (data.menuLabel === 'Edit.Redo') { - editorManager.redo() + if (activeFocusIsInput()) { + document.execCommand('redo') + } else { + editorManager.redo() + } } else if (data.menuLabel === 'View.Orthographic view') { settingsActor.send({ type: 'set.modeling.cameraProjection',