diff --git a/src/components/ProjectSidebarMenu.tsx b/src/components/ProjectSidebarMenu.tsx
index 8dc1fca1a..0528f8ed1 100644
--- a/src/components/ProjectSidebarMenu.tsx
+++ b/src/components/ProjectSidebarMenu.tsx
@@ -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'}
>
@@ -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',
diff --git a/src/components/Settings/AllSettingsFields.tsx b/src/components/Settings/AllSettingsFields.tsx
index 4eaf7d04e..df24e9701 100644
--- a/src/components/Settings/AllSettingsFields.tsx
+++ b/src/components/Settings/AllSettingsFields.tsx
@@ -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
diff --git a/src/components/SettingsAuthProvider.tsx b/src/components/SettingsAuthProvider.tsx
index 9c464036e..bf30b99da 100644
--- a/src/components/SettingsAuthProvider.tsx
+++ b/src/components/SettingsAuthProvider.tsx
@@ -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 (
{
- 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)
}
},
},
diff --git a/src/components/UserSidebarMenu.tsx b/src/components/UserSidebarMenu.tsx
index 56aa8a7ef..fc05beb65 100644
--- a/src/components/UserSidebarMenu.tsx
+++ b/src/components/UserSidebarMenu.tsx
@@ -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)
},
},
{
diff --git a/src/hooks/useAbsoluteFilePath.ts b/src/hooks/useAbsoluteFilePath.ts
index fb3828d2d..4e9c9dc37 100644
--- a/src/hooks/useAbsoluteFilePath.ts
+++ b/src/hooks/useAbsoluteFilePath.ts
@@ -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)
)
}
diff --git a/src/hooks/useRefreshSettings.ts b/src/hooks/useRefreshSettings.ts
index edabf5376..5caf44c04 100644
--- a/src/hooks/useRefreshSettings.ts
+++ b/src/hooks/useRefreshSettings.ts
@@ -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
diff --git a/src/lib/paths.ts b/src/lib/paths.ts
index 71b63c8c0..6c9226e84 100644
--- a/src/lib/paths.ts
+++ b/src/lib/paths.ts
@@ -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
diff --git a/src/lib/routeLoaders.ts b/src/lib/routeLoaders.ts
index 2b67ff597..a03b168bd 100644
--- a/src/lib/routeLoaders.ts
+++ b/src/lib/routeLoaders.ts
@@ -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()
diff --git a/src/lib/tauriFS.ts b/src/lib/tauriFS.ts
index c9cf838f2..964078420 100644
--- a/src/lib/tauriFS.ts
+++ b/src/lib/tauriFS.ts
@@ -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
diff --git a/src/routes/Home.tsx b/src/routes/Home.tsx
index a14594c04..1f4658927 100644
--- a/src/routes/Home.tsx
+++ b/src/routes/Home.tsx
@@ -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 = () => {
Loaded from{' '}
{settings.app.projectDirectory.current}
diff --git a/src/routes/Onboarding/Introduction.tsx b/src/routes/Onboarding/Introduction.tsx
index 7dc5ae1ca..a98070138 100644
--- a/src/routes/Onboarding/Introduction.tsx
+++ b/src/routes/Onboarding/Introduction.tsx
@@ -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()
diff --git a/src/routes/Onboarding/index.tsx b/src/routes/Onboarding/index.tsx
index ea9f12988..5be7929cf 100644
--- a/src/routes/Onboarding/index.tsx
+++ b/src/routes/Onboarding/index.tsx
@@ -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])
}
diff --git a/src/routes/Settings.tsx b/src/routes/Settings.tsx
index 13aaabcf4..41ec745f0 100644
--- a/src/routes/Settings.tsx
+++ b/src/routes/Settings.tsx
@@ -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')
diff --git a/src/routes/SignIn.tsx b/src/routes/SignIn.tsx
index 36bba0d5a..ba6c2ff88 100644
--- a/src/routes/SignIn.tsx
+++ b/src/routes/SignIn.tsx
@@ -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 = () => {