Compare commits

..

4 Commits

Author SHA1 Message Date
6e2274a6c4 Bump @tweenjs/tween.js from 23.1.2 to 25.0.0
Bumps [@tweenjs/tween.js](https://github.com/tweenjs/tween.js) from 23.1.2 to 25.0.0.
- [Release notes](https://github.com/tweenjs/tween.js/releases)
- [Commits](https://github.com/tweenjs/tween.js/compare/v23.1.2...v25.0.0)

---
updated-dependencies:
- dependency-name: "@tweenjs/tween.js"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 03:47:59 +00:00
4b9f71c994 Update machine-api spec (#3346)
* YOYO NEW API SPEC!

* New machine-api types

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-08-11 18:04:30 -07:00
e86a5622c8 the printer slicer expects mm (#3341)
* the printer slicer expects mm

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* empty

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-08-09 18:05:18 -07:00
a503d1ce50 Use named constants for settings URL query params (#3333) 2024-08-09 02:47:25 -04:00
36 changed files with 205 additions and 335 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View File

@ -79,7 +79,8 @@
"$ref": "#/components/schemas/Result"
}
],
"description": "The result of the info command."
"description": "The result of the info command.",
"nullable": true
},
"sequence_id": {
"allOf": [
@ -93,7 +94,6 @@
"required": [
"command",
"module",
"result",
"sequence_id"
],
"type": "object"

View File

@ -31,7 +31,7 @@
"@tauri-apps/plugin-shell": "^2.0.0-beta.7",
"@tauri-apps/plugin-updater": "^2.0.0-beta.6",
"@ts-stack/markdown": "^1.5.0",
"@tweenjs/tween.js": "^23.1.1",
"@tweenjs/tween.js": "^25.0.0",
"@xstate/inspect": "^0.8.0",
"@xstate/react": "^3.2.2",
"codemirror": "^6.0.1",

View File

@ -9,7 +9,7 @@ import { useHotkeys } from 'react-hotkeys-hook'
import { getNormalisedCoordinates } from './lib/utils'
import { useLoaderData, useNavigate } from 'react-router-dom'
import { type IndexLoaderData } from 'lib/types'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
import { onboardingPaths } from 'routes/Onboarding/paths'
import { useEngineConnectionSubscriptions } from 'hooks/useEngineConnectionSubscriptions'
@ -28,7 +28,7 @@ import { CoreDumpManager } from 'lib/coredump'
import { UnitsMenu } from 'components/UnitsMenu'
export function App() {
useRefreshSettings(paths.FILE + 'SETTINGS')
useRefreshSettings(PATHS.FILE + 'SETTINGS')
const { project, file } = useLoaderData() as IndexLoaderData
const navigate = useNavigate()
const filePath = useAbsoluteFilePath()
@ -63,7 +63,7 @@ export function App() {
})
useHotkeyWrapper(
[isTauri() ? 'mod + ,' : 'shift + mod + ,'],
() => navigate(filePath + paths.SETTINGS),
() => navigate(filePath + PATHS.SETTINGS),
{
splitKey: '|',
}

View File

@ -20,7 +20,7 @@ import { WasmErrBanner } from 'components/WasmErrBanner'
import { CommandBar } from 'components/CommandBar/CommandBar'
import ModelingMachineProvider from 'components/ModelingMachineProvider'
import FileMachineProvider from 'components/FileMachineProvider'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import {
fileLoader,
homeLoader,
@ -45,7 +45,7 @@ import { AppStateProvider } from 'AppState'
const router = createBrowserRouter([
{
loader: settingsLoader,
id: paths.INDEX,
id: PATHS.INDEX,
/* Make sure auth is the outermost provider or else we will have
* inefficient re-renders, use the react profiler to see. */
element: (
@ -64,7 +64,7 @@ const router = createBrowserRouter([
errorElement: <ErrorPage />,
children: [
{
path: paths.INDEX,
path: PATHS.INDEX,
loader: async () => {
const inTauri = isTauri()
if (inTauri) {
@ -78,21 +78,21 @@ const router = createBrowserRouter([
// Redirect to the file if we have a file path.
if (appState.current_file) {
return redirect(
paths.FILE + '/' + encodeURIComponent(appState.current_file)
PATHS.FILE + '/' + encodeURIComponent(appState.current_file)
)
}
}
}
return inTauri
? redirect(paths.HOME)
: redirect(paths.FILE + '/%2F' + BROWSER_PROJECT_NAME)
? redirect(PATHS.HOME)
: redirect(PATHS.FILE + '/%2F' + BROWSER_PROJECT_NAME)
},
},
{
loader: fileLoader,
id: paths.FILE,
path: paths.FILE + '/:id',
id: PATHS.FILE,
path: PATHS.FILE + '/:id',
element: (
<Auth>
<FileMachineProvider>
@ -109,7 +109,7 @@ const router = createBrowserRouter([
),
children: [
{
id: paths.FILE + 'SETTINGS',
id: PATHS.FILE + 'SETTINGS',
loader: settingsLoader,
children: [
{
@ -118,11 +118,11 @@ const router = createBrowserRouter([
element: <></>,
},
{
path: makeUrlPathRelative(paths.SETTINGS),
path: makeUrlPathRelative(PATHS.SETTINGS),
element: <Settings />,
},
{
path: makeUrlPathRelative(paths.ONBOARDING.INDEX),
path: makeUrlPathRelative(PATHS.ONBOARDING.INDEX),
element: <Onboarding />,
children: onboardingRoutes,
},
@ -131,7 +131,7 @@ const router = createBrowserRouter([
],
},
{
path: paths.HOME,
path: PATHS.HOME,
element: (
<Auth>
<Outlet />
@ -139,24 +139,24 @@ const router = createBrowserRouter([
<CommandBar />
</Auth>
),
id: paths.HOME,
id: PATHS.HOME,
loader: homeLoader,
children: [
{
index: true,
element: <></>,
id: paths.HOME + 'SETTINGS',
id: PATHS.HOME + 'SETTINGS',
loader: settingsLoader,
},
{
path: makeUrlPathRelative(paths.SETTINGS),
path: makeUrlPathRelative(PATHS.SETTINGS),
loader: settingsLoader,
element: <Settings />,
},
],
},
{
path: paths.SIGN_IN,
path: PATHS.SIGN_IN,
element: <SignIn />,
},
],

View File

@ -84,11 +84,7 @@ import {
createPipeSubstitution,
findUniqueName,
} from 'lang/modifyAst'
import {
Selection,
Selections,
getEventForSegmentSelection,
} from 'lib/selections'
import { Selections, getEventForSegmentSelection } from 'lib/selections'
import { getTangentPointFromPreviousArc } from 'lib/utils2d'
import { createGridHelper, orthoScale, perspScale } from './helpers'
import { Models } from '@kittycad/lib'
@ -102,11 +98,6 @@ import {
import { getThemeColorForThreeJs } from 'lib/theme'
import { err, trap } from 'lib/trap'
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
import {
ArtifactGraph,
ArtifactId,
getPlaneOrFaceFromSelection,
} from 'lang/std/artifactGraph'
type DraftSegment = 'line' | 'tangentialArcTo'
@ -591,20 +582,15 @@ export class SceneEntities {
const _node1 = getNodeFromPath<VariableDeclaration>(
_ast,
sketchPathToNode || [],
['VariableDeclaration', 'ExpressionStatement']
) as { node: { type: string } } | Error
if (trap(_node1)) return Promise.reject(_node1)
const variableDeclarationName = (_node1.node.type === 'VariableDeclaration') ?
(_node1.node as VariableDeclaration).declarations[0]?.id?.name || '' :
''
const sgMemItem = kclManager.programMemory.get(
variableDeclarationName
'VariableDeclaration'
)
if (sgMemItem?.type !== 'SketchGroup') {
return Promise.reject(new Error('SketchGroup not found in programMemory'))
}
const sg: SketchGroup = sgMemItem
if (trap(_node1)) return Promise.reject(_node1)
const variableDeclarationName =
_node1.node?.declarations?.[0]?.id?.name || ''
const sg = kclManager.programMemory.get(
variableDeclarationName
) as SketchGroup
const lastSeg = sg.value.slice(-1)[0] || sg.start
const index = sg.value.length // because we've added a new segment that's not in the memory yet, no need for `-1`
@ -1776,33 +1762,6 @@ export function getParentGroup(
return null
}
export async function planeOrFaceFromSelection({
artifactGraph,
selection,
}: {
artifactGraph: ArtifactGraph
selection: Selection
}): Promise<{
id: ArtifactId
faceDetails: Models['GetSketchModePlane_type']
} | null> {
// If the selection doesn't have an artifactId associated with it, we can't
// do it.
if (!selection.artifactId) return null
const planeOrFace = getPlaneOrFaceFromSelection(
selection.artifactId,
artifactGraph
)
if (!planeOrFace) return null
if (planeOrFace?.type === 'plane') {
const faceDetails = await getFaceDetails(planeOrFace.id)
return { id: planeOrFace.id, faceDetails }
}
// TODO: Handle wall or cap artifact.
return null
}
export function sketchGroupFromPathToNode({
pathToNode,
ast,
@ -1868,51 +1827,11 @@ export function getSketchQuaternion(
return getQuaternionFromZAxis(massageFormats(zAxis))
}
export async function getSketchOrientationDetails(
artifactGraph: ArtifactGraph,
selection: Selection,
sketchPathToNode: PathToNode
): Promise<{
sketchDetails: {
zAxis: [number, number, number]
yAxis: [number, number, number]
origin: [number, number, number]
faceId: string
}
quat: Quaternion
sketchDetails: SketchDetails & { faceId?: string }
}> {
const plane = await planeOrFaceFromSelection({
artifactGraph,
selection,
})
if (plane) {
const details = plane.faceDetails
console.warn('Found plane', plane)
const zAxis: [number, number, number] = [
details.z_axis.x,
details.z_axis.y,
details.z_axis.z,
]
const yAxis: [number, number, number] = [
details.y_axis.x,
details.y_axis.y,
details.y_axis.z,
]
const origin: [number, number, number] = [
details.origin.x,
details.origin.y,
details.origin.z,
]
return {
sketchDetails: {
zAxis,
yAxis,
origin,
faceId: plane.id,
},
}
}
// We couldn't find the plane or face, so try to look at the AST, and find it
// through there.
const sketchGroup = sketchGroupFromPathToNode({
pathToNode: sketchPathToNode,
ast: kclManager.ast,
@ -1924,7 +1843,9 @@ export async function getSketchOrientationDetails(
if (sketchGroup.on.type === 'plane') {
const zAxis = sketchGroup?.on.zAxis
return {
quat: getQuaternionFromZAxis(massageFormats(zAxis)),
sketchDetails: {
sketchPathToNode,
zAxis: [zAxis.x, zAxis.y, zAxis.z],
yAxis: [
sketchGroup.on.yAxis.x,
@ -1943,8 +1864,14 @@ export async function getSketchOrientationDetails(
if (!faceInfo?.origin || !faceInfo?.z_axis || !faceInfo?.y_axis)
return Promise.reject('face info')
const { z_axis, y_axis, origin } = faceInfo
const quaternion = quaternionFromUpNForward(
new Vector3(y_axis.x, y_axis.y, y_axis.z),
new Vector3(z_axis.x, z_axis.y, z_axis.z)
)
return {
quat: quaternion,
sketchDetails: {
sketchPathToNode,
zAxis: [z_axis.x, z_axis.y, z_axis.z],
yAxis: [y_axis.x, y_axis.y, y_axis.z],
origin: [origin.x, origin.y, origin.z],

View File

@ -1,6 +1,6 @@
import { ActionIcon, ActionIconProps } from './ActionIcon'
import React, { ForwardedRef, forwardRef } from 'react'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import { Link } from 'react-router-dom'
import type { LinkProps } from 'react-router-dom'
@ -82,7 +82,7 @@ export const ActionButton = forwardRef((props: ActionButtonProps, ref) => {
return (
<Link
ref={ref as ForwardedRef<HTMLAnchorElement>}
to={to || paths.INDEX}
to={to || PATHS.INDEX}
className={classNames}
{...rest}
>
@ -105,7 +105,7 @@ export const ActionButton = forwardRef((props: ActionButtonProps, ref) => {
return (
<Link
ref={ref as ForwardedRef<HTMLAnchorElement>}
to={to || paths.INDEX}
to={to || PATHS.INDEX}
className={classNames}
{...rest}
target="_blank"

View File

@ -1,7 +1,7 @@
import { useMachine } from '@xstate/react'
import { useNavigate, useRouteLoaderData } from 'react-router-dom'
import { type IndexLoaderData } from 'lib/types'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import React, { createContext } from 'react'
import { toast } from 'react-hot-toast'
import {
@ -38,7 +38,7 @@ export const FileMachineProvider = ({
}) => {
const navigate = useNavigate()
const { commandBarSend } = useCommandsContext()
const { project, file } = useRouteLoaderData(paths.FILE) as IndexLoaderData
const { project, file } = useRouteLoaderData(PATHS.FILE) as IndexLoaderData
const [state, send] = useMachine(fileMachine, {
context: {
@ -50,7 +50,7 @@ export const FileMachineProvider = ({
if (event.data && 'name' in event.data) {
commandBarSend({ type: 'Close' })
navigate(
`${paths.FILE}/${encodeURIComponent(
`${PATHS.FILE}/${encodeURIComponent(
context.selectedDirectory + sep() + event.data.name
)}`
)
@ -60,7 +60,7 @@ export const FileMachineProvider = ({
event.data.path.endsWith(FILE_EXT)
) {
// Don't navigate to newly created directories
navigate(`${paths.FILE}/${encodeURIComponent(event.data.path)}`)
navigate(`${PATHS.FILE}/${encodeURIComponent(event.data.path)}`)
}
},
addFileToRenamingQueue: assign({
@ -130,11 +130,11 @@ export const FileMachineProvider = ({
if (oldPath === file?.path && project?.path) {
// If we just renamed the current file, navigate to the new path
navigate(paths.FILE + '/' + encodeURIComponent(newPath))
navigate(PATHS.FILE + '/' + encodeURIComponent(newPath))
} else if (file?.path.includes(oldPath)) {
// If we just renamed a directory that the current file is in, navigate to the new path
navigate(
paths.FILE +
PATHS.FILE +
'/' +
encodeURIComponent(file.path.replace(oldPath, newDirPath))
)
@ -169,7 +169,7 @@ export const FileMachineProvider = ({
file?.path.includes(event.data.path)) &&
project?.path
) {
navigate(paths.FILE + '/' + encodeURIComponent(project.path))
navigate(PATHS.FILE + '/' + encodeURIComponent(project.path))
}
return `Successfully deleted ${isDir ? 'folder' : 'file'} "${

View File

@ -1,5 +1,5 @@
import type { FileEntry, IndexLoaderData } from 'lib/types'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import { ActionButton } from './ActionButton'
import Tooltip from './Tooltip'
import { Dispatch, useCallback, useEffect, useRef, useState } from 'react'
@ -187,7 +187,7 @@ const FileTreeItem = ({
onFileOpen(fileOrDir.path, project?.path || null)
// Open kcl files
navigate(`${paths.FILE}/${encodeURIComponent(fileOrDir.path)}`)
navigate(`${PATHS.FILE}/${encodeURIComponent(fileOrDir.path)}`)
}
onNavigateToFile?.()
}
@ -447,7 +447,7 @@ export const FileTreeInner = ({
}: {
onNavigateToFile?: () => void
}) => {
const loaderData = useRouteLoaderData(paths.FILE) as IndexLoaderData
const loaderData = useRouteLoaderData(PATHS.FILE) as IndexLoaderData
const { send: fileSend, context: fileContext } = useFileContext()
const { send: modelingSend } = useModelingContext()
const documentHasFocus = useDocumentHasFocus()

View File

@ -4,7 +4,7 @@ import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
import { CustomIcon } from './CustomIcon'
import { useLocation, useNavigate } from 'react-router-dom'
import { createAndOpenNewProject } from 'lib/tauriFS'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath'
import { useLspContext } from './LspProvider'
@ -16,7 +16,7 @@ export function HelpMenu(props: React.PropsWithChildren) {
const location = useLocation()
const { onProjectOpen } = useLspContext()
const filePath = useAbsoluteFilePath()
const isInProject = location.pathname.includes(paths.FILE)
const isInProject = location.pathname.includes(PATHS.FILE)
const navigate = useNavigate()
const { settings } = useSettingsAuthContext()
@ -89,10 +89,10 @@ export function HelpMenu(props: React.PropsWithChildren) {
<HelpMenuItem
as="button"
onClick={() => {
const targetPath = location.pathname.includes(paths.FILE)
? filePath + paths.SETTINGS
: paths.HOME + paths.SETTINGS
navigate(targetPath + '?tab=keybindings')
const targetPath = location.pathname.includes(PATHS.FILE)
? filePath + PATHS.SETTINGS_KEYBINDINGS
: PATHS.HOME + PATHS.SETTINGS_KEYBINDINGS
navigate(targetPath)
}}
>
Keyboard shortcuts
@ -108,7 +108,7 @@ export function HelpMenu(props: React.PropsWithChildren) {
},
})
if (isInProject) {
navigate(filePath + paths.ONBOARDING.INDEX)
navigate(filePath + PATHS.ONBOARDING.INDEX)
} else {
createAndOpenNewProject({ onProjectOpen, navigate })
}

View File

@ -1,7 +1,7 @@
import { APP_VERSION } from 'routes/Settings'
import { CustomIcon } from 'components/CustomIcon'
import Tooltip from 'components/Tooltip'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import { NetworkHealthIndicator } from 'components/NetworkHealthIndicator'
import { HelpMenu } from './HelpMenu'
import { Link, useLocation } from 'react-router-dom'
@ -87,9 +87,9 @@ export function LowerRightControls({
</a>
<Link
to={
location.pathname.includes(paths.FILE)
? filePath + paths.SETTINGS + '?tab=project'
: paths.HOME + paths.SETTINGS
location.pathname.includes(PATHS.FILE)
? filePath + PATHS.SETTINGS_PROJECT
: PATHS.HOME + PATHS.SETTINGS
}
>
<CustomIcon

View File

@ -14,7 +14,7 @@ import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
import { Extension } from '@codemirror/state'
import { LanguageSupport } from '@codemirror/language'
import { useNavigate } from 'react-router-dom'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import { FileEntry } from 'lib/types'
import Worker from 'editor/plugins/lsp/worker.ts?worker'
import {
@ -260,7 +260,7 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
})
if (redirect) {
navigate(paths.HOME)
navigate(PATHS.HOME)
}
}

View File

@ -388,7 +388,8 @@ export const ModelingMachineProvider = ({
},
},
storage: 'ascii',
units: defaultUnit.current,
// Convert all units to mm since that is what the slicer expects.
units: 'mm',
selection: { type: 'default_scene' },
}
@ -589,17 +590,12 @@ export const ModelingMachineProvider = ({
}
},
'animate-to-sketch': async ({ selectionRanges }) => {
const selection = selectionRanges.codeBasedSelections[0]
const sourceRange = selection.range
const sourceRange = selectionRanges.codeBasedSelections[0].range
const sketchPathToNode = getNodePathFromSourceRange(
kclManager.ast,
sourceRange
)
const info = await getSketchOrientationDetails(
engineCommandManager.artifactGraph,
selection,
sketchPathToNode || []
)
const info = await getSketchOrientationDetails(sketchPathToNode || [])
await letEngineAnimateAndSyncCamAfter(
engineCommandManager,
info?.sketchDetails?.faceId || ''

View File

@ -1,5 +1,5 @@
import { FormEvent, useEffect, useRef, useState } from 'react'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import { Link } from 'react-router-dom'
import { ActionButton } from '../ActionButton'
import { FILE_EXT } from 'lib/constants'
@ -79,7 +79,7 @@ function ProjectCard({
>
<Link
data-testid="project-link"
to={`${paths.FILE}/${encodeURIComponent(project.default_file)}`}
to={`${PATHS.FILE}/${encodeURIComponent(project.default_file)}`}
className="flex flex-col flex-1 !no-underline !text-chalkboard-110 dark:!text-chalkboard-10 group-hover:!hue-rotate-0 min-h-[5em] divide-y divide-primary/40 dark:divide-chalkboard-80 group-hover:!divide-primary"
>
{/* <div className="h-36 relative overflow-hidden bg-gradient-to-b from-transparent to-primary/10 rounded-t-sm">

View File

@ -1,7 +1,7 @@
import { Popover, Transition } from '@headlessui/react'
import { ActionButton, ActionButtonProps } from './ActionButton'
import { type IndexLoaderData } from 'lib/types'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import { isTauri } from '../lib/isTauri'
import { Link, useLocation, useNavigate } from 'react-router-dom'
import { Fragment, useMemo } from 'react'
@ -63,7 +63,7 @@ function AppLogoLink({
// Clear the scene and end the session.
engineCommandManager.endSession()
}}
to={paths.HOME}
to={PATHS.HOME}
className={wrapperClassName + ' hover:before:brightness-110'}
>
<Logo className={logoClassName} />
@ -116,10 +116,10 @@ function ProjectMenuPopover({
</>
),
onClick: () => {
const targetPath = location.pathname.includes(paths.FILE)
? filePath + paths.SETTINGS
: paths.HOME + paths.SETTINGS
navigate(targetPath + '?tab=project')
const targetPath = location.pathname.includes(PATHS.FILE)
? filePath + PATHS.SETTINGS_PROJECT
: PATHS.HOME + PATHS.SETTINGS_PROJECT
navigate(targetPath)
},
},
'break',

View File

@ -16,7 +16,7 @@ import { getInitialDefaultDir, showInFolder } from 'lib/tauri'
import toast from 'react-hot-toast'
import { APP_VERSION } from 'routes/Settings'
import { createAndOpenNewProject, getSettingsFolderPaths } from 'lib/tauriFS'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import { useDotDotSlash } from 'hooks/useDotDotSlash'
import { sep } from '@tauri-apps/api/path'
import { ForwardedRef, forwardRef, useEffect } from 'react'
@ -44,8 +44,8 @@ export const AllSettingsFields = forwardRef(
isFileSettings && isTauri()
? decodeURI(
location.pathname
.replace(paths.FILE + '/', '')
.replace(paths.SETTINGS, '')
.replace(PATHS.FILE + '/', '')
.replace(PATHS.SETTINGS, '')
.slice(0, decodeURI(location.pathname).lastIndexOf(sep()))
)
: undefined
@ -70,7 +70,7 @@ export const AllSettingsFields = forwardRef(
if (isFileSettings) {
// If we're in a project, first navigate to the onboarding start here
// so we can trigger the warning screen if necessary
navigate(dotDotSlash(1) + paths.ONBOARDING.INDEX)
navigate(dotDotSlash(1) + PATHS.ONBOARDING.INDEX)
} else {
// If we're in the global settings, create a new project and navigate
// to the onboarding start in that project

View File

@ -1,6 +1,6 @@
import { useMachine } from '@xstate/react'
import { useNavigate, useRouteLoaderData } from 'react-router-dom'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import { authMachine, TOKEN_PERSIST_KEY } from '../machines/authMachine'
import withBaseUrl from '../lib/withBaseURL'
import React, { createContext, useEffect } from 'react'
@ -60,8 +60,8 @@ export const SettingsAuthProvider = ({
}: {
children: React.ReactNode
}) => {
const loadedSettings = useRouteLoaderData(paths.INDEX) as typeof settings
const loadedProject = useRouteLoaderData(paths.FILE) as IndexLoaderData
const loadedSettings = useRouteLoaderData(PATHS.INDEX) as typeof settings
const loadedProject = useRouteLoaderData(PATHS.FILE) as IndexLoaderData
return (
<SettingsAuthProviderBase
loadedSettings={loadedSettings}
@ -297,12 +297,12 @@ export const SettingsAuthProviderBase = ({
const [authState, authSend, authActor] = useMachine(authMachine, {
actions: {
goToSignInPage: () => {
navigate(paths.SIGN_IN)
navigate(PATHS.SIGN_IN)
logout()
},
goToIndexPage: () => {
if (window.location.pathname.includes(paths.SIGN_IN)) {
navigate(paths.INDEX)
if (window.location.pathname.includes(PATHS.SIGN_IN)) {
navigate(PATHS.INDEX)
}
},
},

View File

@ -2,7 +2,7 @@ import { Popover, Transition } from '@headlessui/react'
import { ActionButton, ActionButtonProps } from './ActionButton'
import { useLocation, useNavigate } from 'react-router-dom'
import { Fragment, useMemo, useState } from 'react'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import { Models } from '@kittycad/lib'
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath'
@ -39,10 +39,10 @@ const UserSidebarMenu = ({ user }: { user?: User }) => {
),
'data-testid': 'user-settings',
onClick: () => {
const targetPath = location.pathname.includes(paths.FILE)
? filePath + paths.SETTINGS
: paths.HOME + paths.SETTINGS
navigate(targetPath + '?tab=user')
const targetPath = location.pathname.includes(PATHS.FILE)
? filePath + PATHS.SETTINGS_USER
: PATHS.HOME + PATHS.SETTINGS_USER
navigate(targetPath)
},
},
{
@ -50,10 +50,10 @@ const UserSidebarMenu = ({ user }: { user?: User }) => {
Element: 'button',
children: 'Keyboard shortcuts',
onClick: () => {
const targetPath = location.pathname.includes(paths.FILE)
? filePath + paths.SETTINGS
: paths.HOME + paths.SETTINGS
navigate(targetPath + '?tab=keybindings')
const targetPath = location.pathname.includes(PATHS.FILE)
? filePath + PATHS.SETTINGS_KEYBINDINGS
: PATHS.HOME + PATHS.SETTINGS_KEYBINDINGS
navigate(targetPath)
},
},
{

View File

@ -1,11 +1,11 @@
import { type IndexLoaderData } from 'lib/types'
import { BROWSER_PATH, paths } from 'lib/paths'
import { BROWSER_PATH, PATHS } from 'lib/paths'
import { useRouteLoaderData } from 'react-router-dom'
export function useAbsoluteFilePath() {
const routeData = useRouteLoaderData(paths.FILE) as IndexLoaderData
const routeData = useRouteLoaderData(PATHS.FILE) as IndexLoaderData
return (
paths.FILE + '/' + encodeURIComponent(routeData?.file?.path || BROWSER_PATH)
PATHS.FILE + '/' + encodeURIComponent(routeData?.file?.path || BROWSER_PATH)
)
}

View File

@ -1,6 +1,6 @@
import { useRouteLoaderData } from 'react-router-dom'
import { useSettingsAuthContext } from './useSettingsAuthContext'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import { settings } from 'lib/settings/initialSettings'
import { useEffect } from 'react'
@ -10,7 +10,7 @@ import { useEffect } from 'react'
* in conjunction with additional uses of settingsLoader further down the router tree.
* @param routeId - The id defined in Router.tsx to load the settings from.
*/
export function useRefreshSettings(routeId: string = paths.INDEX) {
export function useRefreshSettings(routeId: string = PATHS.INDEX) {
const ctx = useSettingsAuthContext()
const routeData = useRouteLoaderData(routeId) as typeof settings

View File

@ -18,7 +18,6 @@ import {
ProgramMemory,
SourceRange,
SketchGroup,
ExpressionStatement,
} from './wasm'
import {
isNodeSafeToReplacePath,
@ -83,22 +82,15 @@ export function addStartProfileAt(
const _node1 = getNodeFromPath<VariableDeclaration>(
node,
pathToNode,
['VariableDeclaration', 'ExpressionStatement']
) as { node: { type: string } } | Error
'VariableDeclaration'
)
if (err(_node1)) return _node1
const _node = { ...node }
let expr: Value
let variableDeclaration: VariableDeclaration | undefined
if (_node1.node.type === 'VariableDeclaration') {
const node: VariableDeclaration = _node1.node as VariableDeclaration
variableDeclaration = node
expr = node.declarations[0].init
} else if (_node1.node.type === 'ExpressionStatement') {
const node: ExpressionStatement = _node1.node as ExpressionStatement
expr = node.expression
} else {
return new Error(`Unrecognized node type ${_node1.node.type}`)
const variableDeclaration = _node1.node
if (variableDeclaration.type !== 'VariableDeclaration') {
return new Error('variableDeclaration.init.type !== PipeExpression')
}
const _node = { ...node }
const init = variableDeclaration.declarations[0].init
const startProfileAt = createCallExpressionStdLib('startProfileAt', [
createArrayExpression([
createLiteral(roundOff(at[0])),
@ -106,11 +98,11 @@ export function addStartProfileAt(
]),
createPipeSubstitution(),
])
if (expr.type === 'PipeExpression') {
expr.body.splice(1, 0, startProfileAt)
} else if (variableDeclaration) {
if (init.type === 'PipeExpression') {
init.body.splice(1, 0, startProfileAt)
} else {
variableDeclaration.declarations[0].init = createPipeExpression([
expr,
init,
startProfileAt,
])
}

View File

@ -791,7 +791,7 @@ export function isSingleCursorInPipe(
const pathToNode = getNodePathFromSourceRange(ast, selection.range)
const nodeTypes = pathToNode.map(([, type]) => type)
if (nodeTypes.includes('FunctionExpression')) return false
// if (!nodeTypes.includes('VariableDeclaration')) return false
if (!nodeTypes.includes('VariableDeclaration')) return false
if (nodeTypes.includes('PipeExpression')) return true
return false
}

View File

@ -3,8 +3,6 @@ import { Models } from '@kittycad/lib'
import { getNodePathFromSourceRange } from 'lang/queryAst'
import { err } from 'lib/trap'
export type ArtifactId = string
interface CommonCommandProperties {
range: SourceRange
pathToNode: PathToNode
@ -12,20 +10,17 @@ interface CommonCommandProperties {
export interface PlaneArtifact {
type: 'plane'
id: ArtifactId
pathIds: Array<string>
codeRef: CommonCommandProperties
}
export interface PlaneArtifactRich {
type: 'plane'
id: ArtifactId
paths: Array<PathArtifact>
codeRef: CommonCommandProperties
}
export interface PathArtifact {
type: 'path'
id: ArtifactId
planeId: string
segIds: Array<string>
extrusionId: string
@ -35,12 +30,10 @@ export interface PathArtifact {
interface solid2D {
type: 'solid2D'
id: ArtifactId
pathId: string
}
export interface PathArtifactRich {
type: 'path'
id: ArtifactId
plane: PlaneArtifact | WallArtifact
segments: Array<SegmentArtifact>
extrusion: ExtrusionArtifact
@ -49,7 +42,6 @@ export interface PathArtifactRich {
interface SegmentArtifact {
type: 'segment'
id: ArtifactId
pathId: string
surfaceId: string
edgeIds: Array<string>
@ -58,7 +50,6 @@ interface SegmentArtifact {
}
interface SegmentArtifactRich {
type: 'segment'
id: ArtifactId
path: PathArtifact
surf: WallArtifact
edges: Array<ExtrudeEdge>
@ -68,7 +59,6 @@ interface SegmentArtifactRich {
interface ExtrusionArtifact {
type: 'extrusion'
id: ArtifactId
pathId: string
surfaceIds: Array<string>
edgeIds: Array<string>
@ -76,7 +66,6 @@ interface ExtrusionArtifact {
}
interface ExtrusionArtifactRich {
type: 'extrusion'
id: ArtifactId
path: PathArtifact
surfaces: Array<WallArtifact | CapArtifact>
edges: Array<ExtrudeEdge>
@ -85,7 +74,6 @@ interface ExtrusionArtifactRich {
interface WallArtifact {
type: 'wall'
id: ArtifactId
segId: string
edgeCutEdgeIds: Array<string>
extrusionId: string
@ -93,7 +81,6 @@ interface WallArtifact {
}
interface CapArtifact {
type: 'cap'
id: ArtifactId
subType: 'start' | 'end'
edgeCutEdgeIds: Array<string>
extrusionId: string
@ -102,7 +89,6 @@ interface CapArtifact {
interface ExtrudeEdge {
type: 'extrudeEdge'
id: ArtifactId
segId: string
extrusionId: string
edgeId: string
@ -111,7 +97,6 @@ interface ExtrudeEdge {
/** A edgeCut is a more generic term for both fillet or chamfer */
interface EdgeCut {
type: 'edgeCut'
id: ArtifactId
subType: 'fillet' | 'chamfer'
consumedEdgeId: string
edgeIds: Array<string>
@ -121,7 +106,6 @@ interface EdgeCut {
interface EdgeCutEdge {
type: 'edgeCutEdge'
id: ArtifactId
edgeCutId: string
surfaceId: string
}
@ -138,7 +122,7 @@ export type Artifact =
| EdgeCutEdge
| solid2D
export type ArtifactGraph = Map<ArtifactId, Artifact>
export type ArtifactGraph = Map<string, Artifact>
export type EngineCommand = Models['WebSocketRequest_type']
@ -165,7 +149,7 @@ export function createArtifactGraph({
responseMap: ResponseMap
ast: Program
}) {
const myMap = new Map<ArtifactId, Artifact>()
const myMap = new Map<string, Artifact>()
/** see docstring for {@link getArtifactsToUpdate} as to why this is needed */
let currentPlaneId = ''
@ -182,7 +166,7 @@ export function createArtifactGraph({
const artifactsToUpdate = getArtifactsToUpdate({
orderedCommand,
responseMap,
getArtifact: (id: ArtifactId) => myMap.get(id),
getArtifact: (id: string) => myMap.get(id),
currentPlaneId,
ast,
})
@ -226,7 +210,7 @@ function mergeArtifacts(
* It does not mutate the map directly, but returns an array of artifacts to update
*
* @param currentPlaneId is only needed for `start_path` commands because this command does not have a pathId
* instead it relies on the id used with the `enable_sketch_mode` command, so this must be kept track of
* instead it relies on the id used with the `enable_sketch_mode` command, so this much be kept track of
* outside of this function. It would be good to update the `start_path` command to include the planeId so we
* can remove this.
*/
@ -240,11 +224,11 @@ export function getArtifactsToUpdate({
orderedCommand: OrderedCommand
responseMap: ResponseMap
/** Passing in a getter because we don't wan this function to update the map directly */
getArtifact: (id: ArtifactId) => Artifact | undefined
getArtifact: (id: string) => Artifact | undefined
currentPlaneId: string
ast: Program
}): Array<{
id: ArtifactId
id: string
artifact: Artifact
}> {
const pathToNode = getNodePathFromSourceRange(ast, range)
@ -269,7 +253,6 @@ export function getArtifactsToUpdate({
id: currentPlaneId,
artifact: {
type: 'wall',
id: currentPlaneId,
segId: existingPlane.segId,
edgeCutEdgeIds: existingPlane.edgeCutEdgeIds,
extrusionId: existingPlane.extrusionId,
@ -279,10 +262,7 @@ export function getArtifactsToUpdate({
]
} else {
return [
{
id: currentPlaneId,
artifact: { type: 'plane', id: currentPlaneId, pathIds, codeRef },
},
{ id: currentPlaneId, artifact: { type: 'plane', pathIds, codeRef } },
]
}
} else if (cmd.type === 'start_path') {
@ -290,7 +270,6 @@ export function getArtifactsToUpdate({
id,
artifact: {
type: 'path',
id,
segIds: [],
planeId: currentPlaneId,
extrusionId: '',
@ -303,7 +282,7 @@ export function getArtifactsToUpdate({
if (plane?.type === 'plane') {
returnArr.push({
id: currentPlaneId,
artifact: { type: 'plane', id: currentPlaneId, pathIds: [id], codeRef },
artifact: { type: 'plane', pathIds: [id], codeRef },
})
}
if (plane?.type === 'wall') {
@ -311,7 +290,6 @@ export function getArtifactsToUpdate({
id: currentPlaneId,
artifact: {
type: 'wall',
id: currentPlaneId,
segId: plane.segId,
edgeCutEdgeIds: plane.edgeCutEdgeIds,
extrusionId: plane.extrusionId,
@ -326,7 +304,6 @@ export function getArtifactsToUpdate({
id,
artifact: {
type: 'segment',
id,
pathId,
surfaceId: '',
edgeIds: [],
@ -336,22 +313,21 @@ export function getArtifactsToUpdate({
const path = getArtifact(pathId)
if (path?.type === 'path')
returnArr.push({
id: path.id,
id: pathId,
artifact: { ...path, segIds: [id] },
})
if (
response?.type === 'modeling' &&
response.data.modeling_response.type === 'close_path'
) {
const id = response.data.modeling_response.data.face_id
returnArr.push({
id,
artifact: { type: 'solid2D', id, pathId },
id: response.data.modeling_response.data.face_id,
artifact: { type: 'solid2D', pathId },
})
const path = getArtifact(pathId)
if (path?.type === 'path')
returnArr.push({
id: path.id,
id: pathId,
artifact: {
...path,
solid2dId: response.data.modeling_response.data.face_id,
@ -364,7 +340,6 @@ export function getArtifactsToUpdate({
id,
artifact: {
type: 'extrusion',
id,
pathId: cmd.target,
surfaceIds: [],
edgeIds: [],
@ -374,7 +349,7 @@ export function getArtifactsToUpdate({
const path = getArtifact(cmd.target)
if (path?.type === 'path')
returnArr.push({
id: path.id,
id: cmd.target,
artifact: { ...path, extrusionId: id },
})
return returnArr
@ -396,7 +371,6 @@ export function getArtifactsToUpdate({
id: face_id,
artifact: {
type: 'wall',
id: face_id,
segId: curve_id,
edgeCutEdgeIds: [],
extrusionId: path.extrusionId,
@ -404,7 +378,7 @@ export function getArtifactsToUpdate({
},
})
returnArr.push({
id: seg.id,
id: curve_id,
artifact: { ...seg, surfaceId: face_id },
})
const extrusion = getArtifact(path.extrusionId)
@ -429,7 +403,6 @@ export function getArtifactsToUpdate({
id: face_id,
artifact: {
type: 'cap',
id: face_id,
subType: cap === 'bottom' ? 'start' : 'end',
edgeCutEdgeIds: [],
extrusionId: path.extrusionId,
@ -439,7 +412,7 @@ export function getArtifactsToUpdate({
const extrusion = getArtifact(path.extrusionId)
if (extrusion?.type !== 'extrusion') return
returnArr.push({
id: extrusion.id,
id: path.extrusionId,
artifact: {
...extrusion,
surfaceIds: [face_id],
@ -454,7 +427,6 @@ export function getArtifactsToUpdate({
id,
artifact: {
type: 'edgeCut',
id,
subType: cmd.cut_type,
consumedEdgeId: cmd.edge_id,
edgeIds: [],
@ -465,7 +437,7 @@ export function getArtifactsToUpdate({
const consumedEdge = getArtifact(cmd.edge_id)
if (consumedEdge?.type === 'segment') {
returnArr.push({
id: consumedEdge.id,
id: cmd.edge_id,
artifact: { ...consumedEdge, edgeCutId: id },
})
}
@ -492,7 +464,7 @@ export function filterArtifacts<T extends Artifact['type'][]>(
(!predicate ||
predicate(value as Extract<Artifact, { type: T[number] }>))
)
) as Map<ArtifactId, Extract<Artifact, { type: T[number] }>>
) as Map<string, Extract<Artifact, { type: T[number] }>>
}
export function getArtifactsOfTypes<T extends Artifact['type'][]>(
@ -506,7 +478,7 @@ export function getArtifactsOfTypes<T extends Artifact['type'][]>(
predicate?: (value: Extract<Artifact, { type: T[number] }>) => boolean
},
map: ArtifactGraph
): Map<ArtifactId, Extract<Artifact, { type: T[number] }>> {
): Map<string, Extract<Artifact, { type: T[number] }>> {
return new Map(
[...map].filter(
([key, value]) =>
@ -515,7 +487,7 @@ export function getArtifactsOfTypes<T extends Artifact['type'][]>(
(!predicate ||
predicate(value as Extract<Artifact, { type: T[number] }>))
)
) as Map<ArtifactId, Extract<Artifact, { type: T[number] }>>
) as Map<string, Extract<Artifact, { type: T[number] }>>
}
export function getArtifactOfTypes<T extends Artifact['type'][]>(
@ -523,7 +495,7 @@ export function getArtifactOfTypes<T extends Artifact['type'][]>(
key,
types,
}: {
key: ArtifactId
key: string
types: T
},
map: ArtifactGraph
@ -545,7 +517,6 @@ export function expandPlane(
)
return {
type: 'plane',
id: plane.id,
paths: Array.from(paths.values()),
codeRef: plane.codeRef,
}
@ -574,7 +545,6 @@ export function expandPath(
if (err(plane)) return plane
return {
type: 'path',
id: path.id,
segments: Array.from(segs.values()),
extrusion,
plane,
@ -601,7 +571,6 @@ export function expandExtrusion(
if (err(path)) return path
return {
type: 'extrusion',
id: extrusion.id,
surfaces: Array.from(surfs.values()),
edges: Array.from(edges.values()),
path,
@ -637,7 +606,6 @@ export function expandSegment(
return {
type: 'segment',
id: segment.id,
path,
surf,
edges: Array.from(edges.values()),
@ -688,7 +656,7 @@ export function getWallCodeRef(
}
export function getExtrusionFromSuspectedExtrudeSurface(
id: ArtifactId,
id: string,
artifactGraph: ArtifactGraph
): ExtrusionArtifact | Error {
const artifact = getArtifactOfTypes(
@ -703,7 +671,7 @@ export function getExtrusionFromSuspectedExtrudeSurface(
}
export function getExtrusionFromSuspectedPath(
id: ArtifactId,
id: string,
artifactGraph: ArtifactGraph
): ExtrusionArtifact | Error {
const path = getArtifactOfTypes({ key: id, types: ['path'] }, artifactGraph)
@ -713,33 +681,3 @@ export function getExtrusionFromSuspectedPath(
artifactGraph
)
}
/**
* Get the plane or face from a selection.
*
* TODO: Handle sketch on face.
*/
export function getPlaneOrFaceFromSelection(
id: ArtifactId,
artifactGraph: ArtifactGraph
): PlaneArtifactRich | null {
const selection = artifactGraph.get(id)
if (!selection) return null
if (selection.type === 'solid2D') {
const path = artifactGraph.get(selection.pathId)
if (path?.type !== 'path') return null
const plane = artifactGraph.get(path.planeId)
if (plane?.type !== 'plane') return null
return expandPlane(plane, artifactGraph)
} else if (selection.type === 'wall' || selection.type === 'cap') {
const extrusion = artifactGraph.get(selection.extrusionId)
if (extrusion?.type !== 'extrusion') return null
const path = artifactGraph.get(extrusion.pathId)
if (path?.type !== 'path') return null
const plane = artifactGraph.get(path.planeId)
// TODO: For sketch on face, this won't be a plane.
if (plane?.type !== 'plane') return null
return expandPlane(plane, artifactGraph)
}
return null
}

View File

@ -110,7 +110,7 @@ export interface components {
/** @description The reason of the info command. */
reason?: components['schemas']['Reason'] | null
/** @description The result of the info command. */
result: components['schemas']['Result']
result?: components['schemas']['Result'] | null
/** @description The sequence id. */
sequence_id: components['schemas']['SequenceId']
} & {

View File

@ -22,11 +22,16 @@ type OnboardingPaths = {
[K in keyof typeof onboardingPaths]: `/onboarding${(typeof onboardingPaths)[K]}`
}
export const paths = {
const SETTINGS = '/settings' as const
export const PATHS = {
INDEX: '/',
HOME: '/home',
FILE: '/file',
SETTINGS: '/settings',
SETTINGS,
SETTINGS_USER: `${SETTINGS}?tab=user` as const,
SETTINGS_PROJECT: `${SETTINGS}?tab=project` as const,
SETTINGS_KEYBINDINGS: `${SETTINGS}?tab=keybindings` as const,
SIGN_IN: '/signin',
ONBOARDING: prependRoutes(onboardingPaths)('/onboarding') as OnboardingPaths,
} as const

View File

@ -1,7 +1,7 @@
import { ActionFunction, LoaderFunction, redirect } from 'react-router-dom'
import { FileLoaderData, HomeLoaderData, IndexLoaderData } from './types'
import { isTauri } from './isTauri'
import { getProjectMetaByRouteId, paths } from './paths'
import { getProjectMetaByRouteId, PATHS } from './paths'
import { BROWSER_PATH } from 'lib/paths'
import {
BROWSER_FILE_NAME,
@ -54,7 +54,7 @@ export const onboardingRedirectLoader: ActionFunction = async (args) => {
const { settings } = await loadAndValidateSettings()
const onboardingStatus = settings.app.onboardingStatus.current || ''
const notEnRouteToOnboarding = !args.request.url.includes(
paths.ONBOARDING.INDEX
PATHS.ONBOARDING.INDEX
)
// '' is the initial state, 'done' and 'dismissed' are the final states
const hasValidOnboardingStatus =
@ -65,7 +65,7 @@ export const onboardingRedirectLoader: ActionFunction = async (args) => {
if (shouldRedirectToOnboarding) {
return redirect(
makeUrlPathRelative(paths.ONBOARDING.INDEX) + onboardingStatus.slice(1)
makeUrlPathRelative(PATHS.ONBOARDING.INDEX) + onboardingStatus.slice(1)
)
}
@ -89,7 +89,7 @@ export const fileLoader: LoaderFunction = async ({
if (!current_file_name || !current_file_path || !project_name) {
return redirect(
`${paths.FILE}/${encodeURIComponent(
`${PATHS.FILE}/${encodeURIComponent(
`${params.id}${isTauri() ? sep() : '/'}${PROJECT_ENTRYPOINT}`
)}`
)
@ -158,7 +158,7 @@ export const homeLoader: LoaderFunction = async (): Promise<
HomeLoaderData | Response
> => {
if (!isTauri()) {
return redirect(paths.FILE + '/%2F' + BROWSER_PROJECT_NAME)
return redirect(PATHS.FILE + '/%2F' + BROWSER_PROJECT_NAME)
}
const { configuration } = await loadAndValidateSettings()

View File

@ -30,7 +30,6 @@ import { AXIS_GROUP, X_AXIS } from 'clientSideScene/sceneInfra'
import { PathToNodeMap } from 'lang/std/sketchcombos'
import { err } from 'lib/trap'
import {
ArtifactId,
getArtifactOfTypes,
getArtifactsOfTypes,
getCapCodeRef,
@ -57,7 +56,6 @@ export type Selection = {
| 'line'
| 'arc'
| 'all'
artifactId?: ArtifactId
range: SourceRange
}
export type Selections = {
@ -102,11 +100,7 @@ export async function getEventForSelectWithPoint({
type: 'Set selection',
data: {
selectionType: 'singleCodeCursor',
selection: {
artifactId: data.entity_id,
range: codeRef.range,
type: 'solid2D',
},
selection: { range: codeRef.range, type: 'solid2D' },
},
}
}
@ -118,7 +112,6 @@ export async function getEventForSelectWithPoint({
data: {
selectionType: 'singleCodeCursor',
selection: {
artifactId: data.entity_id,
range: codeRef.range,
type: _artifact?.subType === 'end' ? 'end-cap' : 'start-cap',
},
@ -135,11 +128,7 @@ export async function getEventForSelectWithPoint({
type: 'Set selection',
data: {
selectionType: 'singleCodeCursor',
selection: {
artifactId: data.entity_id,
range: codeRef.range,
type: 'extrude-wall',
},
selection: { range: codeRef.range, type: 'extrude-wall' },
},
}
}
@ -148,11 +137,7 @@ export async function getEventForSelectWithPoint({
type: 'Set selection',
data: {
selectionType: 'singleCodeCursor',
selection: {
artifactId: data.entity_id,
range: _artifact.codeRef.range,
type: 'default',
},
selection: { range: _artifact.codeRef.range, type: 'default' },
},
}
}
@ -657,12 +642,9 @@ export function updateSelections(
const nodeMeta = getNodeFromPath<Value>(ast, pathToNode)
if (err(nodeMeta)) return undefined
const node = nodeMeta.node
const prevCodeBasedSelection =
prevSelectionRanges.codeBasedSelections[Number(index)]
return {
artifactId: prevCodeBasedSelection?.artifactId,
range: [node.start, node.end],
type: prevCodeBasedSelection?.type,
type: prevSelectionRanges.codeBasedSelections[Number(index)]?.type,
}
})
.filter((x?: Selection) => x !== undefined) as Selection[]

View File

@ -8,7 +8,7 @@ import {
PROJECT_ENTRYPOINT,
} from 'lib/constants'
import { bracket } from './exampleKcl'
import { paths } from './paths'
import { PATHS } from './paths'
import {
createNewProjectDirectory,
listProjects,
@ -156,8 +156,8 @@ export async function createAndOpenNewProject({
null
)
navigate(
`${paths.FILE}/${encodeURIComponent(newProject.default_file)}${
paths.ONBOARDING.INDEX
`${PATHS.FILE}/${encodeURIComponent(newProject.default_file)}${
PATHS.ONBOARDING.INDEX
}`
)
return newProject

View File

@ -16,7 +16,7 @@ import Loading from 'components/Loading'
import { useMachine } from '@xstate/react'
import { homeMachine } from '../machines/homeMachine'
import { ContextFrom, EventFrom } from 'xstate'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import {
getNextSearchParams,
getSortFunction,
@ -44,7 +44,7 @@ import { ProjectSearchBar, useProjectSearch } from 'components/ProjectSearchBar'
// This route only opens in the Tauri desktop context for now,
// as defined in Router.tsx, so we can use the Tauri APIs and types.
const Home = () => {
useRefreshSettings(paths.HOME + 'SETTINGS')
useRefreshSettings(PATHS.HOME + 'SETTINGS')
const { commandBarSend } = useCommandsContext()
const navigate = useNavigate()
const { projects: loadedProjects } = useLoaderData() as HomeLoaderData
@ -63,7 +63,7 @@ const Home = () => {
})
useHotkeys(
isTauri() ? 'mod+,' : 'shift+mod+,',
() => navigate(paths.HOME + paths.SETTINGS),
() => navigate(PATHS.HOME + PATHS.SETTINGS),
{
splitKey: '|',
}
@ -91,7 +91,7 @@ const Home = () => {
null
)
commandBarSend({ type: 'Close' })
navigate(`${paths.FILE}/${encodeURIComponent(projectPath)}`)
navigate(`${PATHS.FILE}/${encodeURIComponent(projectPath)}`)
}
},
toastSuccess: (_, event) => toast.success((event.data || '') + ''),
@ -276,7 +276,7 @@ const Home = () => {
<p className="my-4 text-sm text-chalkboard-80 dark:text-chalkboard-30">
Loaded from{' '}
<Link
to="settings?tab=user#projectDirectory"
to={`${PATHS.SETTINGS_USER}#projectDirectory`}
className="text-chalkboard-90 dark:text-chalkboard-20 underline underline-offset-2"
>
{settings.app.projectDirectory.current}

View File

@ -11,7 +11,7 @@ import { APP_NAME } from 'lib/constants'
import { useState } from 'react'
import { useLspContext } from 'components/LspProvider'
import { IndexLoaderData } from 'lib/types'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import { useFileContext } from 'hooks/useFileContext'
/**
@ -51,7 +51,7 @@ function OnboardingResetWarning(props: OnboardingResetWarningProps) {
function OnboardingWarningDesktop(props: OnboardingResetWarningProps) {
const navigate = useNavigate()
const dismiss = useDismiss()
const loaderData = useRouteLoaderData(paths.FILE) as IndexLoaderData
const loaderData = useRouteLoaderData(PATHS.FILE) as IndexLoaderData
const { context: fileContext } = useFileContext()
const { onProjectClose, onProjectOpen } = useLspContext()

View File

@ -15,7 +15,7 @@ import UserMenu from './UserMenu'
import ProjectMenu from './ProjectMenu'
import Export from './Export'
import FutureWork from './FutureWork'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath'
import { ActionButton } from 'components/ActionButton'
import { onboardingPaths } from 'routes/Onboarding/paths'
@ -103,7 +103,7 @@ export function useNextClick(newStatus: string) {
type: 'set.app.onboardingStatus',
data: { level: 'user', value: newStatus },
})
navigate(filePath + paths.ONBOARDING.INDEX.slice(0, -1) + newStatus)
navigate(filePath + PATHS.ONBOARDING.INDEX.slice(0, -1) + newStatus)
}, [filePath, newStatus, send, navigate])
}

View File

@ -1,7 +1,7 @@
import { SettingsLevel } from 'lib/settings/settingsTypes'
import { useLocation, useNavigate, useSearchParams } from 'react-router-dom'
import { useHotkeys } from 'react-hotkeys-hook'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import { useDotDotSlash } from 'hooks/useDotDotSlash'
import { Fragment, useEffect, useRef } from 'react'
import { Dialog, Transition } from '@headlessui/react'
@ -21,9 +21,9 @@ export const APP_VERSION = isTauri()
export const Settings = () => {
const navigate = useNavigate()
const [searchParams, setSearchParams] = useSearchParams()
const close = () => navigate(location.pathname.replace(paths.SETTINGS, ''))
const close = () => navigate(location.pathname.replace(PATHS.SETTINGS, ''))
const location = useLocation()
const isFileSettings = location.pathname.includes(paths.FILE)
const isFileSettings = location.pathname.includes(PATHS.FILE)
const searchParamTab =
(searchParams.get('tab') as SettingsLevel | 'keybindings') ??
(isFileSettings ? 'project' : 'user')

View File

@ -2,7 +2,7 @@ import { ActionButton } from '../components/ActionButton'
import { isTauri } from '../lib/isTauri'
import { VITE_KC_SITE_BASE_URL, VITE_KC_API_BASE_URL } from '../env'
import { Themes, getSystemTheme } from '../lib/theme'
import { paths } from 'lib/paths'
import { PATHS } from 'lib/paths'
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
import { APP_NAME } from 'lib/constants'
import { login } from 'lib/tauri'
@ -75,7 +75,7 @@ const SignIn = () => {
<ActionButton
Element="link"
to={`${VITE_KC_SITE_BASE_URL}${
paths.SIGN_IN
PATHS.SIGN_IN
}?callbackUrl=${encodeURIComponent(
typeof window !== 'undefined' &&
window.location.href.replace('signin', '')

View File

@ -2227,7 +2227,12 @@
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9"
integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==
"@tweenjs/tween.js@^23.1.1", "@tweenjs/tween.js@~23.1.1":
"@tweenjs/tween.js@^25.0.0":
version "25.0.0"
resolved "https://registry.yarnpkg.com/@tweenjs/tween.js/-/tween.js-25.0.0.tgz#7266baebcc3affe62a3a54318a3ea82d904cd0b9"
integrity sha512-XKLA6syeBUaPzx4j3qwMqzzq+V4uo72BnlbOjmuljLrRqdsd3qnzvZZoxvMHZ23ndsRS4aufU6JOZYpCbU6T1A==
"@tweenjs/tween.js@~23.1.1":
version "23.1.2"
resolved "https://registry.yarnpkg.com/@tweenjs/tween.js/-/tween.js-23.1.2.tgz#4e5357fd6742f5aa50447d3fa808aed4cda93ed7"
integrity sha512-kMCNaZCJugWI86xiEHaY338CU5JpD0B97p1j1IKNn/Zto8PgACjQx0UxbHjmOcLl/dDOBnItwD07KmCs75pxtQ==
@ -7712,7 +7717,16 @@ string-natural-compare@^3.0.1:
resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4"
integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@ -7790,7 +7804,14 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@ -8666,7 +8687,7 @@ workerpool@6.2.1:
resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343"
integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@ -8684,6 +8705,15 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"