diff --git a/apps/dotcom/client/src/routeDefs.ts b/apps/dotcom/client/src/routeDefs.ts
new file mode 100644
index 000000000000..ef96bb812d0d
--- /dev/null
+++ b/apps/dotcom/client/src/routeDefs.ts
@@ -0,0 +1,91 @@
+import { assert } from 'tldraw'
+
+export const ROUTES = {
+ legacyRoot: '/',
+ legacyNewPage: '/new',
+ legacyNewPage2: '/r',
+ legacyRoom: '/r/:roomId',
+ touchscreenSidePanel: '/ts-side',
+ legacyRoomHistory: '/r/:boardId/history',
+ legacyRoomHistorySnapshot: '/r/:boardId/history/:timestamp',
+ legacySnapshot: '/s/:roomId',
+ legacyReadonly: '/ro/:roomId',
+ legacyReadonlyOld: '/v/:roomId',
+
+ tlaRoot: `/q`,
+ tlaFile: `/q/f/:fileSlug`,
+ tlaLocalFile: `/q/lf/:fileSlug`,
+ tlaPlayground: `/q/playground`,
+ tlaPublish: `/q/p/:fileSlug`,
+} as const
+
+export const routes: {
+ [key in keyof typeof ROUTES]: PathFn<(typeof ROUTES)[key]>
+} = Object.fromEntries(
+ Object.entries(ROUTES).map(([key, path]) => [
+ key,
+ ((routeParamsOrOptions: any, options: any) => {
+ if (path.includes('/:')) {
+ return compilePath(path, routeParamsOrOptions, options)
+ } else {
+ return compilePath(path, null, routeParamsOrOptions)
+ }
+ }) satisfies PathFn,
+ ])
+) as any
+
+type ExtractParamNamesFromPath = route extends `/${infer path}`
+ ? ExtractParamNamesFromPathSegments>
+ : never
+
+type SplitPath = path extends `${infer segment}/${infer rest}`
+ ? segment | SplitPath
+ : path
+
+type ExtractParamNamesFromPathSegments = segments extends `:${infer param}`
+ ? param
+ : never
+
+interface PathOptions {
+ searchParams?: ConstructorParameters[0]
+ asUrl?: boolean
+}
+
+type PathFn = path extends `${string}:${string}:${string}`
+ ? // has at least two params
+ (
+ routeParams: Record, string>,
+ searchParams?: PathOptions
+ ) => string
+ : path extends `${string}:${string}`
+ ? // only has one param, so we can have a single string
+ (param: string, searchParams?: PathOptions) => string
+ : (searchParams?: PathOptions) => string
+
+function compilePath(
+ path: string,
+ routeParams: string | Record | null,
+ options?: PathOptions
+) {
+ const search = new URLSearchParams(options?.searchParams).toString()
+ if (!path.includes(':')) {
+ assert(
+ routeParams === null || Object.keys(routeParams).length === 0,
+ `Route params are not allowed for path ${path}`
+ )
+ return path + (search ? `?${search}` : '')
+ }
+ assert(routeParams !== null, `Route params are required for path ${path}`)
+
+ path =
+ path.replace(/:\w+/g, (match) =>
+ // if there's only one param, routeParams will be a string
+ typeof routeParams === 'string' ? routeParams : routeParams[match.slice(1)]
+ ) + (search ? `?${search}` : '')
+
+ if (options?.asUrl) {
+ return `${window.location.origin}${path}`
+ }
+
+ return path
+}
diff --git a/apps/dotcom/client/src/routes.tsx b/apps/dotcom/client/src/routes.tsx
index 67b0702a7cf1..2e257d7577dd 100644
--- a/apps/dotcom/client/src/routes.tsx
+++ b/apps/dotcom/client/src/routes.tsx
@@ -1,10 +1,4 @@
import { captureException } from '@sentry/react'
-import {
- READ_ONLY_LEGACY_PREFIX,
- READ_ONLY_PREFIX,
- ROOM_PREFIX,
- SNAPSHOT_PREFIX,
-} from '@tldraw/dotcom-shared'
import { TLRemoteSyncError, TLSyncErrorCloseEventReason } from '@tldraw/sync-core'
import { Suspense, lazy, useEffect } from 'react'
import { Helmet } from 'react-helmet-async'
@@ -12,9 +6,9 @@ import { Outlet, Route, createRoutesFromElements, useRouteError } from 'react-ro
import { DefaultErrorFallback } from './components/DefaultErrorFallback/DefaultErrorFallback'
import { ErrorPage } from './components/ErrorPage/ErrorPage'
import { notFound } from './pages/not-found'
+import { ROUTES } from './routeDefs'
import { IntlProvider } from './tla/utils/i18n'
import { TlaNotFoundError } from './tla/utils/notFoundError'
-import { PREFIX } from './tla/utils/urls'
const LoginRedirectPage = lazy(() => import('./components/LoginRedirectPage/LoginRedirectPage'))
@@ -71,55 +65,40 @@ export const router = createRoutesFromElements(
}}
>
}>
- import('./pages/root')} />
+ import('./pages/root')} />
{/* We don't want to index multiplayer rooms */}
}>
}>
- import('./pages/new')} />
- import('./pages/new')} />
- import('./pages/public-touchscreen-side-panel')} />
+ import('./pages/new')} />
+ import('./pages/new')} />
import('./pages/public-multiplayer')}
+ path={ROUTES.touchscreenSidePanel}
+ lazy={() => import('./pages/public-touchscreen-side-panel')}
/>
- import('./pages/history')} />
+ import('./pages/public-multiplayer')} />
+ import('./pages/history')} />
import('./pages/history-snapshot')}
/>
+ import('./pages/public-snapshot')} />
import('./pages/public-snapshot')}
- />
- import('./pages/public-readonly-legacy')}
/>
- import('./pages/public-readonly')}
- />
+ import('./pages/public-readonly')} />
{/* begin tla */}
}>
- import('./tla/pages/local-file')}
- />
+ import('./tla/pages/local-file')} />
import('./tla/providers/TlaRootProviders')}>
- import('./tla/pages/local')} />
- {/* import('./tla/pages/playground')} /> */}
+ import('./tla/pages/local')} />
+ {/* import('./tla/pages/playground')} /> */}
{/* File view */}
- import('./tla/pages/file')}
- />
- import('./tla/pages/publish')}
- />
+ import('./tla/pages/file')} />
+ import('./tla/pages/publish')} />
{/* Views that require login */}
import('./tla/providers/RequireSignedInUser')}>
diff --git a/apps/dotcom/client/src/tla/components/TlaEditor/SlurpFailure.tsx b/apps/dotcom/client/src/tla/components/TlaEditor/SlurpFailure.tsx
index 427782ab6e1d..15594cb982cf 100644
--- a/apps/dotcom/client/src/tla/components/TlaEditor/SlurpFailure.tsx
+++ b/apps/dotcom/client/src/tla/components/TlaEditor/SlurpFailure.tsx
@@ -7,8 +7,8 @@ import {
TldrawUiDialogHeader,
TldrawUiDialogTitle,
} from 'tldraw'
+import { routes } from '../../../routeDefs'
import { F } from '../../utils/i18n'
-import { getLocalFilePath } from '../../utils/urls'
import { ExternalLink } from '../ExternalLink/ExternalLink'
export function SlurpFailure({
@@ -46,7 +46,7 @@ export function SlurpFailure({
-
-
+
diff --git a/apps/dotcom/client/src/tla/components/TlaErrorContent/TlaErrorContent.tsx b/apps/dotcom/client/src/tla/components/TlaErrorContent/TlaErrorContent.tsx
index 080ad850db8f..6b16e0ac2dc1 100644
--- a/apps/dotcom/client/src/tla/components/TlaErrorContent/TlaErrorContent.tsx
+++ b/apps/dotcom/client/src/tla/components/TlaErrorContent/TlaErrorContent.tsx
@@ -1,7 +1,7 @@
import classNames from 'classnames'
import { Link } from 'react-router-dom'
+import { routes } from '../../../routeDefs'
import { F } from '../../utils/i18n'
-import { getRootPath } from '../../utils/urls'
import styles from './error.module.css'
type TlaPageErrorType =
@@ -12,7 +12,7 @@ type TlaPageErrorType =
function ErrorLinkHome() {
return (
-
+
)
diff --git a/apps/dotcom/client/src/tla/components/TlaFileMenu/TlaFileMenu.tsx b/apps/dotcom/client/src/tla/components/TlaFileMenu/TlaFileMenu.tsx
index 90cccb151a5a..8aa103702e34 100644
--- a/apps/dotcom/client/src/tla/components/TlaFileMenu/TlaFileMenu.tsx
+++ b/apps/dotcom/client/src/tla/components/TlaFileMenu/TlaFileMenu.tsx
@@ -17,13 +17,13 @@ import {
useDialogs,
useToasts,
} from 'tldraw'
+import { routes } from '../../../routeDefs'
import { TldrawApp } from '../../app/TldrawApp'
import { useApp } from '../../hooks/useAppState'
import { useIsFileOwner } from '../../hooks/useIsFileOwner'
import { TLAppUiEventSource, useTldrawAppUiEvents } from '../../utils/app-ui-events'
import { copyTextToClipboard } from '../../utils/copy'
import { defineMessages, useMsg } from '../../utils/i18n'
-import { getFilePath, getShareableFileUrl } from '../../utils/urls'
import { TlaDeleteFileDialog } from '../dialogs/TlaDeleteFileDialog'
const messages = defineMessages({
@@ -92,7 +92,7 @@ function FileItems({
const isOwner = useIsFileOwner(fileId)
const handleCopyLinkClick = useCallback(() => {
- const url = getShareableFileUrl(fileId)
+ const url = routes.tlaFile(fileId, { asUrl: true })
copyTextToClipboard(url)
addToast({
id: 'copied-link',
@@ -106,7 +106,9 @@ function FileItems({
const file = app.getFile(fileId)
if (!file) return
app.createFile({ id: newFileId, name: getDuplicateName(file, app) })
- navigate(getFilePath(newFileId), { state: { mode: 'duplicate', duplicateId: fileId } })
+ navigate(routes.tlaFile(newFileId), {
+ state: { mode: 'duplicate', duplicateId: fileId },
+ })
}, [app, fileId, navigate])
const handleDeleteClick = useCallback(() => {
diff --git a/apps/dotcom/client/src/tla/components/TlaFileShareMenu/Tabs/TlaInviteTab.tsx b/apps/dotcom/client/src/tla/components/TlaFileShareMenu/Tabs/TlaInviteTab.tsx
index d2ecf18b6b65..a864cfab743e 100644
--- a/apps/dotcom/client/src/tla/components/TlaFileShareMenu/Tabs/TlaInviteTab.tsx
+++ b/apps/dotcom/client/src/tla/components/TlaFileShareMenu/Tabs/TlaInviteTab.tsx
@@ -1,13 +1,13 @@
import { TlaFile } from '@tldraw/dotcom-shared'
import { useCallback } from 'react'
import { useEditor, useValue } from 'tldraw'
+import { routes } from '../../../../routeDefs'
import { useApp } from '../../../hooks/useAppState'
import { useIsFileOwner } from '../../../hooks/useIsFileOwner'
import { useTldrawUser } from '../../../hooks/useUser'
import { useTldrawAppUiEvents } from '../../../utils/app-ui-events'
import { copyTextToClipboard } from '../../../utils/copy'
import { F, defineMessages, useMsg } from '../../../utils/i18n'
-import { getShareableFileUrl } from '../../../utils/urls'
import { TlaSelect } from '../../TlaSelect/TlaSelect'
import { TlaSwitch } from '../../TlaSwitch/TlaSwitch'
import {
@@ -48,7 +48,7 @@ export function TlaInviteTab({ fileId }: { fileId: string }) {
)}
{isShared && }
- {isShared && }
+ {isShared && }
>
)
@@ -140,7 +140,7 @@ function TlaCopyLinkButton({ fileId }: { isShared: boolean; fileId: string }) {
const trackEvent = useTldrawAppUiEvents()
const handleCopyLinkClick = useCallback(() => {
- const url = getShareableFileUrl(fileId)
+ const url = routes.tlaFile(fileId, { asUrl: true })
copyTextToClipboard(editor.createDeepLink({ url }).toString())
// no toasts please
trackEvent('copy-share-link', { source: 'file-share-menu' })
diff --git a/apps/dotcom/client/src/tla/components/TlaFileShareMenu/Tabs/TlaPublishTab.tsx b/apps/dotcom/client/src/tla/components/TlaFileShareMenu/Tabs/TlaPublishTab.tsx
index 09e116240fb8..3cc03e478af7 100644
--- a/apps/dotcom/client/src/tla/components/TlaFileShareMenu/Tabs/TlaPublishTab.tsx
+++ b/apps/dotcom/client/src/tla/components/TlaFileShareMenu/Tabs/TlaPublishTab.tsx
@@ -3,11 +3,11 @@ import { TlaFile } from '@tldraw/dotcom-shared'
import { useCallback, useState } from 'react'
import { useParams } from 'react-router-dom'
import { useEditor } from 'tldraw'
+import { routes } from '../../../../routeDefs'
import { useApp } from '../../../hooks/useAppState'
import { useTldrawAppUiEvents } from '../../../utils/app-ui-events'
import { copyTextToClipboard } from '../../../utils/copy'
import { F, FormattedRelativeTime } from '../../../utils/i18n'
-import { getShareablePublishUrl } from '../../../utils/urls'
import { TlaButton } from '../../TlaButton/TlaButton'
import { TlaSwitch } from '../../TlaSwitch/TlaSwitch'
import { TlaTabsPage } from '../../TlaTabs/TlaTabs'
@@ -67,7 +67,7 @@ export function TlaPublishTab({ file }: { file: TlaFile }) {
trackEvent('unpublish-file', { source: 'file-share-menu' })
}, [app, auth, file.id, isOwner, trackEvent])
- const publishShareUrl = publishedSlug ? getShareablePublishUrl(publishedSlug) : null
+ const publishShareUrl = publishedSlug ? routes.tlaPublish(publishedSlug, { asUrl: true }) : null
const secondsSince = Math.min(0, Math.floor((Date.now() - file.lastPublished) / 1000))
const learnMoreUrl = 'https://tldraw.notion.site/Publishing-1283e4c324c08059a1a1d9ba9833ddc9'
diff --git a/apps/dotcom/client/src/tla/components/TlaSidebar/components/TlaSidebarCreateFileButton.tsx b/apps/dotcom/client/src/tla/components/TlaSidebar/components/TlaSidebarCreateFileButton.tsx
index d08250354b2d..468c0e4e07c6 100644
--- a/apps/dotcom/client/src/tla/components/TlaSidebar/components/TlaSidebarCreateFileButton.tsx
+++ b/apps/dotcom/client/src/tla/components/TlaSidebar/components/TlaSidebarCreateFileButton.tsx
@@ -1,10 +1,10 @@
import { useCallback, useRef } from 'react'
import { useNavigate } from 'react-router-dom'
import { tltime } from 'tldraw'
+import { routes } from '../../../../routeDefs'
import { useApp } from '../../../hooks/useAppState'
import { useTldrawAppUiEvents } from '../../../utils/app-ui-events'
import { useMsg } from '../../../utils/i18n'
-import { getFilePath } from '../../../utils/urls'
import { TlaIcon } from '../../TlaIcon/TlaIcon'
import styles from '../sidebar.module.css'
import { messages } from './sidebar-shared'
@@ -22,7 +22,7 @@ export function TlaSidebarCreateFileButton() {
const res = app.createFile()
if (res.ok) {
const { file } = res.value
- navigate(getFilePath(file.id), { state: { mode: 'create' } })
+ navigate(routes.tlaFile(file.id), { state: { mode: 'create' } })
trackEvent('create-file', { source: 'sidebar' })
rCanCreate.current = false
tltime.setTimeout('can create again', () => (rCanCreate.current = true), 1000)
diff --git a/apps/dotcom/client/src/tla/components/TlaSidebar/components/TlaSidebarFileLink.tsx b/apps/dotcom/client/src/tla/components/TlaSidebar/components/TlaSidebarFileLink.tsx
index 901d899b55b4..f4661a903838 100644
--- a/apps/dotcom/client/src/tla/components/TlaSidebar/components/TlaSidebarFileLink.tsx
+++ b/apps/dotcom/client/src/tla/components/TlaSidebar/components/TlaSidebarFileLink.tsx
@@ -3,11 +3,11 @@ import classNames from 'classnames'
import { KeyboardEvent, useEffect, useRef, useState } from 'react'
import { Link, useParams } from 'react-router-dom'
import { preventDefault, useContainer, useValue } from 'tldraw'
+import { routes } from '../../../../routeDefs'
import { useApp } from '../../../hooks/useAppState'
import { useIsFileOwner } from '../../../hooks/useIsFileOwner'
import { useTldrawAppUiEvents } from '../../../utils/app-ui-events'
import { F } from '../../../utils/i18n'
-import { getFilePath } from '../../../utils/urls'
import { TlaIcon } from '../../TlaIcon/TlaIcon'
import {
TlaTooltipArrow,
@@ -48,7 +48,7 @@ export function TlaSidebarFileLink({ item, testId }: { item: RecentFile; testId:
isActive={isActive}
isOwnFile={isOwnFile}
fileName={app.getFileName(fileId)}
- href={getFilePath(fileId)}
+ href={routes.tlaFile(fileId)}
/>
)
}
diff --git a/apps/dotcom/client/src/tla/components/dialogs/TlaDeleteFileDialog.tsx b/apps/dotcom/client/src/tla/components/dialogs/TlaDeleteFileDialog.tsx
index ad1c11d31e1a..c3c523141a86 100644
--- a/apps/dotcom/client/src/tla/components/dialogs/TlaDeleteFileDialog.tsx
+++ b/apps/dotcom/client/src/tla/components/dialogs/TlaDeleteFileDialog.tsx
@@ -10,11 +10,11 @@ import {
TldrawUiDialogHeader,
TldrawUiDialogTitle,
} from 'tldraw'
+import { routes } from '../../../routeDefs'
import { useApp } from '../../hooks/useAppState'
import { useIsFileOwner } from '../../hooks/useIsFileOwner'
import { useTldrawAppUiEvents } from '../../utils/app-ui-events'
import { F } from '../../utils/i18n'
-import { getFilePath } from '../../utils/urls'
export function TlaDeleteFileDialog({ fileId, onClose }: { fileId: string; onClose(): void }) {
const app = useApp()
@@ -32,11 +32,11 @@ export function TlaDeleteFileDialog({ fileId, onClose }: { fileId: string; onClo
if (recentFiles.length === 0) {
const result = app.createFile()
if (result.ok) {
- navigate(getFilePath(result.value.file.id), { state: { mode: 'create' } })
+ navigate(routes.tlaFile(result.value.file.id), { state: { mode: 'create' } })
trackEvent('delete-file', { source: 'file-menu' })
}
} else {
- navigate(getFilePath(recentFiles[0].fileId))
+ navigate(routes.tlaFile(recentFiles[0].fileId))
}
onClose()
}, [auth, app, fileId, onClose, navigate, trackEvent])
diff --git a/apps/dotcom/client/src/tla/hooks/useTldrFileDrop.ts b/apps/dotcom/client/src/tla/hooks/useTldrFileDrop.ts
index 870fe172864d..74d9ce3f0b3f 100644
--- a/apps/dotcom/client/src/tla/hooks/useTldrFileDrop.ts
+++ b/apps/dotcom/client/src/tla/hooks/useTldrFileDrop.ts
@@ -2,9 +2,9 @@ import { useAuth } from '@clerk/clerk-react'
import { DragEvent, useCallback, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { Editor, TLStoreSnapshot, parseTldrawJsonFile, tlmenus, useToasts } from 'tldraw'
+import { routes } from '../../routeDefs'
import { globalEditor } from '../../utils/globalEditor'
import { defineMessages, useIntl } from '../utils/i18n'
-import { getFilePath } from '../utils/urls'
import { useApp } from './useAppState'
const messages = defineMessages({
@@ -66,7 +66,7 @@ export function useTldrFileDrop() {
keepOpen: true,
})
if (results.slugs.length > 0) {
- navigate(getFilePath(results.slugs[0]), { state: { mode: 'create' } })
+ navigate(routes.tlaFile(results.slugs[0]))
}
}
},
diff --git a/apps/dotcom/client/src/tla/layouts/TlaErrorLayout/TlaErrorLayout.tsx b/apps/dotcom/client/src/tla/layouts/TlaErrorLayout/TlaErrorLayout.tsx
index 56c5642e3d77..ab4b49ab84ea 100644
--- a/apps/dotcom/client/src/tla/layouts/TlaErrorLayout/TlaErrorLayout.tsx
+++ b/apps/dotcom/client/src/tla/layouts/TlaErrorLayout/TlaErrorLayout.tsx
@@ -1,8 +1,8 @@
import { ReactNode } from 'react'
import { useNavigate } from 'react-router-dom'
+import { routes } from '../../../routeDefs'
import { TlaCloseButton } from '../../components/TlaCloseButton/TlaCloseButton'
import { usePreventAccidentalDrops } from '../../hooks/usePreventAccidentalDrops'
-import { getRootPath } from '../../utils/urls'
import styles from './error-layout.module.css'
export function TlaErrorLayout({ children }: { children: ReactNode }) {
@@ -11,7 +11,7 @@ export function TlaErrorLayout({ children }: { children: ReactNode }) {
return (
-
navigate(getRootPath())} />
+ navigate(routes.tlaRoot())} />
diff --git a/apps/dotcom/client/src/tla/pages/local.tsx b/apps/dotcom/client/src/tla/pages/local.tsx
index ece91bbb417b..682a66631304 100644
--- a/apps/dotcom/client/src/tla/pages/local.tsx
+++ b/apps/dotcom/client/src/tla/pages/local.tsx
@@ -2,13 +2,13 @@ import { useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { assert, react } from 'tldraw'
import { LocalEditor } from '../../components/LocalEditor'
+import { routes } from '../../routeDefs'
import { globalEditor } from '../../utils/globalEditor'
import { SneakyDarkModeSync } from '../components/TlaEditor/SneakyDarkModeSync'
import { components } from '../components/TlaEditor/TlaEditor'
import { useMaybeApp } from '../hooks/useAppState'
import { TlaAnonLayout } from '../layouts/TlaAnonLayout/TlaAnonLayout'
import { clearShouldSlurpFile, getShouldSlurpFile, setShouldSlurpFile } from '../utils/slurping'
-import { getFilePath } from '../utils/urls'
export function Component() {
const app = useMaybeApp()
@@ -21,7 +21,10 @@ export function Component() {
const res = app.slurpFile()
if (res.ok) {
clearShouldSlurpFile()
- navigate(getFilePath(res.value.file.id), { state: { mode: 'create' }, replace: true })
+ navigate(routes.tlaFile(res.value.file.id), {
+ state: { mode: 'create' },
+ replace: true,
+ })
} else {
// if the user has too many files we end up here.
// don't slurp the file and when they log out they'll
@@ -37,12 +40,15 @@ export function Component() {
// result is only false if the user reached their file limit so
// we don't need to handle that case here since they have no files
if (result.ok) {
- navigate(getFilePath(result.value.file.id), { state: { mode: 'create' }, replace: true })
+ navigate(routes.tlaFile(result.value.file.id), {
+ state: { mode: 'create' },
+ replace: true,
+ })
}
return
}
- navigate(getFilePath(recentFiles[0].fileId), { replace: true })
+ navigate(routes.tlaFile(recentFiles[0].fileId), { replace: true })
}, [app, navigate])
if (!app) return
diff --git a/apps/dotcom/client/src/tla/providers/RequireSignedInUser.tsx b/apps/dotcom/client/src/tla/providers/RequireSignedInUser.tsx
index da8704fa8f80..5947141c105d 100644
--- a/apps/dotcom/client/src/tla/providers/RequireSignedInUser.tsx
+++ b/apps/dotcom/client/src/tla/providers/RequireSignedInUser.tsx
@@ -1,12 +1,12 @@
import { Navigate, Outlet } from 'react-router-dom'
+import { routes } from '../../routeDefs'
import { useMaybeApp } from '../hooks/useAppState'
-import { getRootPath } from '../utils/urls'
export function Component() {
const app = useMaybeApp()
if (!app) {
// todo: add a back-to location in the location state, redirect back to here after sign in
- return
+ return
}
return
}
diff --git a/apps/dotcom/client/src/tla/providers/TlaRootProviders.tsx b/apps/dotcom/client/src/tla/providers/TlaRootProviders.tsx
index 5b34f119f005..798fb9e53b54 100644
--- a/apps/dotcom/client/src/tla/providers/TlaRootProviders.tsx
+++ b/apps/dotcom/client/src/tla/providers/TlaRootProviders.tsx
@@ -14,6 +14,7 @@ import {
useToasts,
useValue,
} from 'tldraw'
+import { routes } from '../../routeDefs'
import { globalEditor } from '../../utils/globalEditor'
import { MaybeForceUserRefresh } from '../components/MaybeForceUserRefresh/MaybeForceUserRefresh'
import { components } from '../components/TlaEditor/TlaEditor'
@@ -22,7 +23,6 @@ import { UserProvider } from '../hooks/useUser'
import '../styles/tla.css'
import { IntlProvider, setupCreateIntl } from '../utils/i18n'
import { getLocalSessionState, updateLocalSessionState } from '../utils/local-session-state'
-import { getRootPath } from '../utils/urls'
const assetUrls = getAssetUrlsByImport()
@@ -48,7 +48,7 @@ export function Component() {
>
-
+
{container && (
diff --git a/apps/dotcom/client/src/tla/utils/urls.ts b/apps/dotcom/client/src/tla/utils/urls.ts
deleted file mode 100644
index 6f0c417ef7d1..000000000000
--- a/apps/dotcom/client/src/tla/utils/urls.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-export const PREFIX = {
- tla: 'q',
- file: 'f',
- localFile: 'lf',
- publish: 'p',
-}
-
-export function buildUrl({ pathname }: { pathname: string }): string {
- return `/${PREFIX.tla}${pathname}`
-}
-
-export function getRootPath() {
- return buildUrl({ pathname: '/' })
-}
-
-export function getDebugPath() {
- return buildUrl({ pathname: '/debug' })
-}
-
-export function getProfilePath() {
- return buildUrl({ pathname: '/profile' })
-}
-
-export function getFilePath(fileSlug: string) {
- return buildUrl({ pathname: `/${PREFIX.file}/${fileSlug}` })
-}
-
-export function getLocalFilePath(persistenceKey: string) {
- return buildUrl({ pathname: `/${PREFIX.localFile}/${persistenceKey}` })
-}
-
-export function getPublishPath(publishSlug: string) {
- return buildUrl({ pathname: `/${PREFIX.publish}/${publishSlug}` })
-}
-
-function absoluteUrl(path: string) {
- return `${window.location.origin}${path}`
-}
-
-export function getShareableFileUrl(fileId: string): string {
- return absoluteUrl(getFilePath(fileId))
-}
-
-export function getShareablePublishUrl(publishSlug: string): string {
- return absoluteUrl(getPublishPath(publishSlug))
-}
diff --git a/apps/dotcom/client/src/utils/sharing.ts b/apps/dotcom/client/src/utils/sharing.ts
index efe8ad321546..acb581645633 100644
--- a/apps/dotcom/client/src/utils/sharing.ts
+++ b/apps/dotcom/client/src/utils/sharing.ts
@@ -23,6 +23,7 @@ import {
fetch,
isShape,
} from 'tldraw'
+import { routes } from '../routeDefs'
import { writeToClipboard } from './clipboard'
import { cloneAssetForShare } from './cloneAssetForShare'
import { getParentOrigin, isInIframe } from './iFrame'
@@ -107,7 +108,7 @@ export function useSharing(): TLUiOverrides {
handleUiEvent('leave-shared-project', {})
- navigate('/')
+ navigate(routes.legacyRoot())
},
}
actions[SHARE_PROJECT_ACTION] = {
diff --git a/apps/dotcom/client/src/utils/useFileSystem.tsx b/apps/dotcom/client/src/utils/useFileSystem.tsx
index acbd6cf1dae7..80f5a1cf896b 100644
--- a/apps/dotcom/client/src/utils/useFileSystem.tsx
+++ b/apps/dotcom/client/src/utils/useFileSystem.tsx
@@ -12,6 +12,7 @@ import {
serializeTldrawJsonBlob,
transact,
} from 'tldraw'
+import { routes } from '../routeDefs'
import { shouldClearDocument } from './shouldClearDocument'
import { shouldOverrideDocument } from './shouldOverrideDocument'
import { useHandleUiEvents } from './useHandleUiEvent'
@@ -76,7 +77,7 @@ export function useFileSystem({ isMultiplayer }: { isMultiplayer: boolean }): TL
readonlyOk: true,
async onSelect(source) {
handleUiEvent('create-new-shared-project', { source })
- navigate('/new')
+ navigate(routes.legacyNewPage())
},
}
actions[NEW_PROJECT_ACTION] = {