Merge branch 'main' into achalmers/remove-tanarc-to
This commit is contained in:
		@ -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: '|',
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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 />,
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
@ -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"
 | 
			
		||||
 | 
			
		||||
@ -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'} "${
 | 
			
		||||
 | 
			
		||||
@ -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()
 | 
			
		||||
 | 
			
		||||
@ -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 })
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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">
 | 
			
		||||
 | 
			
		||||
@ -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',
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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}
 | 
			
		||||
 | 
			
		||||
@ -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()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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')
 | 
			
		||||
 | 
			
		||||
@ -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', '')
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user