Make it impossible to crash app while extruding (#2224)

Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch>
This commit is contained in:
Frank Noirot
2024-04-24 16:34:56 -04:00
committed by GitHub
parent 2fc7c0d5fd
commit cc6dee8ad4
4 changed files with 30 additions and 24 deletions

View File

@ -3,13 +3,12 @@ import { useCommandsContext } from 'hooks/useCommandsContext'
import { useKclContext } from 'lang/KclProvider' import { useKclContext } from 'lang/KclProvider'
import { CommandArgument } from 'lib/commandTypes' import { CommandArgument } from 'lib/commandTypes'
import { import {
ResolvedSelectionType,
canSubmitSelectionArg, canSubmitSelectionArg,
getSelectionType, getSelectionType,
getSelectionTypeDisplayText, getSelectionTypeDisplayText,
} from 'lib/selections' } from 'lib/selections'
import { modelingMachine } from 'machines/modelingMachine' import { modelingMachine } from 'machines/modelingMachine'
import { useEffect, useRef, useState } from 'react' import { useCallback, useEffect, useRef, useState } from 'react'
import { useHotkeys } from 'react-hotkeys-hook' import { useHotkeys } from 'react-hotkeys-hook'
import { StateFrom } from 'xstate' import { StateFrom } from 'xstate'
@ -30,13 +29,13 @@ function CommandBarSelectionInput({
const { commandBarState, commandBarSend } = useCommandsContext() const { commandBarState, commandBarSend } = useCommandsContext()
const [hasSubmitted, setHasSubmitted] = useState(false) const [hasSubmitted, setHasSubmitted] = useState(false)
const selection = useSelector(arg.machineActor, selectionSelector) const selection = useSelector(arg.machineActor, selectionSelector)
const [selectionsByType, setSelectionsByType] = useState< const initSelectionsByType = useCallback(() => {
'none' | ResolvedSelectionType[] const selectionRangeEnd = selection.codeBasedSelections[0]?.range[1]
>( return !selectionRangeEnd || selectionRangeEnd === code.length
selection.codeBasedSelections[0]?.range[1] === code.length
? 'none' ? 'none'
: getSelectionType(selection) : getSelectionType(selection)
) }, [selection, code])
const selectionsByType = initSelectionsByType()
const [canSubmitSelection, setCanSubmitSelection] = useState<boolean>( const [canSubmitSelection, setCanSubmitSelection] = useState<boolean>(
canSubmitSelectionArg(selectionsByType, arg) canSubmitSelectionArg(selectionsByType, arg)
) )
@ -51,17 +50,14 @@ function CommandBarSelectionInput({
inputRef.current?.focus() inputRef.current?.focus()
}, [selection, inputRef]) }, [selection, inputRef])
useEffect(() => {
setSelectionsByType(
selection.codeBasedSelections[0]?.range[1] === code.length
? 'none'
: getSelectionType(selection)
)
}, [selection])
// Fast-forward through this arg if it's marked as skippable // Fast-forward through this arg if it's marked as skippable
// and we have a valid selection already // and we have a valid selection already
useEffect(() => { useEffect(() => {
console.log('selection input effect', {
selectionsByType,
canSubmitSelection,
arg,
})
setCanSubmitSelection(canSubmitSelectionArg(selectionsByType, arg)) setCanSubmitSelection(canSubmitSelectionArg(selectionsByType, arg))
const argValue = commandBarState.context.argumentsToSubmit[arg.name] const argValue = commandBarState.context.argumentsToSubmit[arg.name]
if (canSubmitSelection && arg.skip && argValue === undefined) { if (canSubmitSelection && arg.skip && argValue === undefined) {

View File

@ -267,10 +267,12 @@ export const ModelingMachineProvider = ({
'has valid extrude selection': ({ selectionRanges }) => { 'has valid extrude selection': ({ selectionRanges }) => {
// A user can begin extruding if they either have 1+ faces selected or nothing selected // A user can begin extruding if they either have 1+ faces selected or nothing selected
// TODO: I believe this guard only allows for extruding a single face at a time // TODO: I believe this guard only allows for extruding a single face at a time
if (selectionRanges.codeBasedSelections.length < 1) return false
const isPipe = isSketchPipe(selectionRanges) const isPipe = isSketchPipe(selectionRanges)
if (isSelectionLastLine(selectionRanges, codeManager.code)) if (
selectionRanges.codeBasedSelections.length === 0 ||
isSelectionLastLine(selectionRanges, codeManager.code)
)
return true return true
if (!isPipe) return false if (!isPipe) return false

View File

@ -420,7 +420,13 @@ export function getSelectionTypeDisplayText(
const selectionsByType = getSelectionType(selection) const selectionsByType = getSelectionType(selection)
return (selectionsByType as Exclude<typeof selectionsByType, 'none'>) return (selectionsByType as Exclude<typeof selectionsByType, 'none'>)
.map(([type, count]) => `${count} ${type}${count > 1 ? 's' : ''}`) .map(
// Hack for showing "face" instead of "extrude-wall" in command bar text
([type, count]) =>
`${count} ${type.replace('extrude-wall', 'face')}${
count > 1 ? 's' : ''
}`
)
.join(', ') .join(', ')
} }

View File

@ -31,9 +31,11 @@ export function useCalculateKclExpression({
newVariableInsertIndex: number newVariableInsertIndex: number
setNewVariableName: (a: string) => void setNewVariableName: (a: string) => void
} { } {
const { programMemory } = useKclContext() const { programMemory, code } = useKclContext()
const { context } = useModelingContext() const { context } = useModelingContext()
const selectionRange = context.selectionRanges.codeBasedSelections[0].range const selectionRange:
| (typeof context.selectionRanges.codeBasedSelections)[number]['range']
| undefined = context.selectionRanges.codeBasedSelections[0]?.range
const inputRef = useRef<HTMLInputElement>(null) const inputRef = useRef<HTMLInputElement>(null)
const [availableVarInfo, setAvailableVarInfo] = useState< const [availableVarInfo, setAvailableVarInfo] = useState<
ReturnType<typeof findAllPreviousVariables> ReturnType<typeof findAllPreviousVariables>
@ -67,7 +69,7 @@ export function useCalculateKclExpression({
} else { } else {
setIsNewVariableNameUnique(true) setIsNewVariableNameUnique(true)
} }
}, [newVariableName]) }, [programMemory, newVariableName])
useEffect(() => { useEffect(() => {
if (!programMemory || !selectionRange) return if (!programMemory || !selectionRange) return
@ -81,8 +83,8 @@ export function useCalculateKclExpression({
useEffect(() => { useEffect(() => {
const execAstAndSetResult = async () => { const execAstAndSetResult = async () => {
const code = `const __result__ = ${value}` const _code = `const __result__ = ${value}`
const ast = parse(code) const ast = parse(_code)
const _programMem: any = { root: {}, return: null } const _programMem: any = { root: {}, return: null }
availableVarInfo.variables.forEach(({ key, value }) => { availableVarInfo.variables.forEach(({ key, value }) => {
_programMem.root[key] = { type: 'userVal', value, __meta: [] } _programMem.root[key] = { type: 'userVal', value, __meta: [] }
@ -111,7 +113,7 @@ export function useCalculateKclExpression({
setCalcResult('NAN') setCalcResult('NAN')
setValueNode(null) setValueNode(null)
}) })
}, [value, availableVarInfo]) }, [value, availableVarInfo, code, kclManager.programMemory])
return { return {
valueNode, valueNode,