Files
modeling-app/src/Router.tsx
Frank Noirot 3b7b4f85a1 Update onboarding to V1 browser and desktop flows (#6714)
* Remove unused `telemetryLoader`

* Remove onboarding redirect behavior

* Allow subRoute to be passed to navigateToProject

* Replace warning dialog routes with toasts

* Wire up new utilities and toasts to UI components

* Add home sidebar buttons for tutorial flow

* Rename menu item

* Add flex-1 so home-layout fills available space

* Remove onboarding avatar tests, they are becoming irrelevant

* Consolidate onboarding tests to one longer one

and update it to not use pixel color checks, and use fixtures.

* Shorten warning toast button text

* tsc, lint, and circular deps

* Update circular dep file

* Fix mistakes made in circular update tweaking

* One more dumb created circular dep

* Update src/routes/Onboarding/utils.tsx

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>

* Fix narrow screen home layout breaking

* fix: kevin, navigation routes fixed

* fix: filename parsing is correct now for onboarding with the last file sep

* Fix e2e test state checks that are diff on Linux

* Create onboarding project entirely through systemIOMachine

* Fix Windows path construction

* Make utility to verify a string is an onboarding value

* Little biome formatting suggestion fix

* Units onboarding step was not using OnboardingButtons

* Add type checking of next and previous status, fix useNextClick

* Update `OnboardingStatus` type on WASM side

* Make onboarding different on browser and web, placeholder component

* Show proof of concept with custom content per route

* Make text type args not insta dismiss when you click anywhere

* Make some utility hooks for the onboarding

* Update requestedProjectName along with requestedProjectName

* Build out a rough draft of desktop onboarding

* Remove unused onboarding route files

* Build out rough draft of browser onboarding content

* @jgomez720 browser flow feedback

* @jgomez420 desktop feedback

* tsc and lints

* Tweaks

* Import is dead, long live Add files

* What's up with my inability to type "highlight"?

* Codespell and String casting

* Update browser sample to be axial fan

* lint and tsc

* codespell again

* Remove unused nightmare function `useDemoCode`

* Add a few unit tests

* Update desktop to use bulk file creation from #6747

* Oops overwrote main.kcl on the modify with text-to-cad step

* Undo the dumb use of `sep` that I introduced

* Fix up project test

which was fragile to the number of steps in the onboarding smh

* Fix up onboarding flow test

* typo

---------

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
2025-05-09 00:37:21 +00:00

206 lines
5.9 KiB
TypeScript

import { useMemo } from 'react'
import toast from 'react-hot-toast'
import {
Outlet,
RouterProvider,
createBrowserRouter,
createHashRouter,
redirect,
} from 'react-router-dom'
import { App } from '@src/App'
import { Auth } from '@src/Auth'
import { CommandBar } from '@src/components/CommandBar/CommandBar'
import DownloadAppBanner from '@src/components/DownloadAppBanner'
import { ErrorPage } from '@src/components/ErrorPage'
import FileMachineProvider from '@src/components/FileMachineProvider'
import ModelingMachineProvider from '@src/components/ModelingMachineProvider'
import { WasmErrBanner } from '@src/components/WasmErrBanner'
import { NetworkContext } from '@src/hooks/useNetworkContext'
import { useNetworkStatus } from '@src/hooks/useNetworkStatus'
import { coreDump } from '@src/lang/wasm'
import {
ASK_TO_OPEN_QUERY_PARAM,
BROWSER_PROJECT_NAME,
} from '@src/lib/constants'
import { CoreDumpManager } from '@src/lib/coredump'
import useHotkeyWrapper from '@src/lib/hotkeyWrapper'
import { isDesktop } from '@src/lib/isDesktop'
import makeUrlPathRelative from '@src/lib/makeUrlPathRelative'
import { PATHS } from '@src/lib/paths'
import { fileLoader, homeLoader } from '@src/lib/routeLoaders'
import {
codeManager,
engineCommandManager,
rustContext,
} from '@src/lib/singletons'
import { reportRejection } from '@src/lib/trap'
import { useToken } from '@src/lib/singletons'
import RootLayout from '@src/Root'
import Home from '@src/routes/Home'
import { OnboardingRootRoute, onboardingRoutes } from '@src/routes/Onboarding'
import { Settings } from '@src/routes/Settings'
import SignIn from '@src/routes/SignIn'
import { Telemetry } from '@src/routes/Telemetry'
const createRouter = isDesktop() ? createHashRouter : createBrowserRouter
const router = createRouter([
{
id: PATHS.INDEX,
element: <RootLayout />,
// Gotcha: declaring errorElement on the root will unmount the element causing our forever React components to unmount.
// Leave errorElement on the child components, this allows for the entire react context on error pages as well.
children: [
{
path: PATHS.INDEX,
errorElement: <ErrorPage />,
loader: async ({ request }) => {
const onDesktop = isDesktop()
const url = new URL(request.url)
if (onDesktop) {
return redirect(PATHS.HOME + (url.search || ''))
} else {
const searchParams = new URLSearchParams(url.search)
if (!searchParams.has(ASK_TO_OPEN_QUERY_PARAM)) {
return redirect(
PATHS.FILE + '/%2F' + BROWSER_PROJECT_NAME + (url.search || '')
)
}
}
return null
},
},
{
loader: fileLoader,
id: PATHS.FILE,
path: PATHS.FILE + '/:id',
errorElement: <ErrorPage />,
element: (
<Auth>
<FileMachineProvider>
<ModelingMachineProvider>
<CoreDump />
<Outlet />
<App />
<CommandBar />
{
// @ts-ignore
!isDesktop() && import.meta.env.PROD && <DownloadAppBanner />
}
</ModelingMachineProvider>
<WasmErrBanner />
</FileMachineProvider>
</Auth>
),
children: [
{
id: PATHS.FILE + 'SETTINGS',
children: [
{
path: makeUrlPathRelative(PATHS.SETTINGS),
element: <Settings />,
},
{
path: makeUrlPathRelative(PATHS.ONBOARDING),
element: <OnboardingRootRoute />,
children: onboardingRoutes,
},
],
},
{
id: PATHS.FILE + 'TELEMETRY',
children: [
{
path: makeUrlPathRelative(PATHS.TELEMETRY),
element: <Telemetry />,
},
],
},
],
},
{
path: PATHS.HOME,
errorElement: <ErrorPage />,
element: (
<Auth>
<Outlet />
<Home />
<CommandBar />
</Auth>
),
id: PATHS.HOME,
loader: homeLoader,
children: [
{
index: true,
element: <></>,
id: PATHS.HOME + 'SETTINGS',
},
{
path: makeUrlPathRelative(PATHS.SETTINGS),
element: <Settings />,
},
{
path: makeUrlPathRelative(PATHS.TELEMETRY),
element: <Telemetry />,
},
],
},
{
path: PATHS.SIGN_IN,
errorElement: <ErrorPage />,
element: <SignIn />,
},
],
},
])
/**
* All routes in the app, used in src/index.tsx
* @returns RouterProvider
*/
export const Router = () => {
const networkStatus = useNetworkStatus()
return (
<NetworkContext.Provider value={networkStatus}>
<RouterProvider router={router} />
</NetworkContext.Provider>
)
}
function CoreDump() {
const token = useToken()
const coreDumpManager = useMemo(
() =>
new CoreDumpManager(
engineCommandManager,
codeManager,
rustContext,
token
),
[]
)
useHotkeyWrapper(['mod + shift + .'], () => {
toast
.promise(
coreDump(coreDumpManager, true),
{
loading: 'Starting core dump...',
success: 'Core dump completed successfully',
error: 'Error while exporting core dump',
},
{
success: {
// Note: this extended duration is especially important for Playwright e2e testing
// default duration is 2000 - https://react-hot-toast.com/docs/toast#default-durations
duration: 6000,
},
}
)
.catch(reportRejection)
})
return null
}