Add option to navigate to new project from file menu (#3876)

Rel #3861 TLD-2551

This PR adds a menu item to both multiplayer and local editor
components, to create a new shared project in the file menu.

I think it might be helpful to add a dialog as well. At the moment it
feels a bit sudden to jump to a new page right after clicking. However
it's non-destructive, and it would add an unnecessary extra step. What
do you think?



### Change Type

<!--  Please select a 'Scope' label ️ -->

- [ ] `sdk` — Changes the tldraw SDK
- [x] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [ ] `internal` — Does not affect user-facing stuff

<!--  Please select a 'Type' label ️ -->

- [ ] `bugfix` — Bug fix
- [x] `feature` — New feature
- [ ] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know


### Test Plan

1. Add a step-by-step description of how to test your PR here.
2.

- [ ] Unit Tests
- [ ] End to end tests

### Release Notes

- Add a brief release note for your PR here.
This commit is contained in:
Taha 2024-06-05 17:58:05 +01:00 committed by GitHub
parent 5d7f368fd6
commit 7071b5fee2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 22 additions and 3 deletions

View file

@ -4,7 +4,12 @@ import {
LEAVE_SHARED_PROJECT_ACTION, LEAVE_SHARED_PROJECT_ACTION,
SHARE_PROJECT_ACTION, SHARE_PROJECT_ACTION,
} from '../utils/sharing' } from '../utils/sharing'
import { NEW_PROJECT_ACTION, OPEN_FILE_ACTION, SAVE_FILE_COPY_ACTION } from '../utils/useFileSystem' import {
NEW_PROJECT_ACTION,
NEW_SHARED_PROJECT_ACTION,
OPEN_FILE_ACTION,
SAVE_FILE_COPY_ACTION,
} from '../utils/useFileSystem'
export function LocalFileMenu() { export function LocalFileMenu() {
const actions = useActions() const actions = useActions()
@ -13,6 +18,7 @@ export function LocalFileMenu() {
<TldrawUiMenuSubmenu id="file" label="menu.file"> <TldrawUiMenuSubmenu id="file" label="menu.file">
<TldrawUiMenuGroup id="file-actions"> <TldrawUiMenuGroup id="file-actions">
<TldrawUiMenuItem {...actions[NEW_PROJECT_ACTION]} /> <TldrawUiMenuItem {...actions[NEW_PROJECT_ACTION]} />
<TldrawUiMenuItem {...actions[NEW_SHARED_PROJECT_ACTION]} />
<TldrawUiMenuItem {...actions[OPEN_FILE_ACTION]} /> <TldrawUiMenuItem {...actions[OPEN_FILE_ACTION]} />
<TldrawUiMenuItem {...actions[SAVE_FILE_COPY_ACTION]} /> <TldrawUiMenuItem {...actions[SAVE_FILE_COPY_ACTION]} />
</TldrawUiMenuGroup> </TldrawUiMenuGroup>
@ -32,6 +38,7 @@ export function MultiplayerFileMenu() {
<TldrawUiMenuItem {...actions[SAVE_FILE_COPY_ACTION]} /> <TldrawUiMenuItem {...actions[SAVE_FILE_COPY_ACTION]} />
</TldrawUiMenuGroup> </TldrawUiMenuGroup>
<TldrawUiMenuGroup id="share"> <TldrawUiMenuGroup id="share">
<TldrawUiMenuItem {...actions[NEW_SHARED_PROJECT_ACTION]} />
<TldrawUiMenuItem {...actions[FORK_PROJECT_ACTION]} /> <TldrawUiMenuItem {...actions[FORK_PROJECT_ACTION]} />
<TldrawUiMenuItem {...actions[LEAVE_SHARED_PROJECT_ACTION]} /> <TldrawUiMenuItem {...actions[LEAVE_SHARED_PROJECT_ACTION]} />
</TldrawUiMenuGroup> </TldrawUiMenuGroup>

View file

@ -35,5 +35,5 @@ export function Component() {
}} }}
/> />
) )
return <Navigate to={`/${ROOM_PREFIX}/${data.slug}`} /> return <Navigate replace to={`/${ROOM_PREFIX}/${data.slug}`} />
} }

View file

@ -1,5 +1,6 @@
import { fileOpen, fileSave } from 'browser-fs-access' import { fileOpen, fileSave } from 'browser-fs-access'
import { useMemo } from 'react' import { useMemo } from 'react'
import { useNavigate } from 'react-router-dom'
import { import {
Editor, Editor,
TLDRAW_FILE_EXTENSION, TLDRAW_FILE_EXTENSION,
@ -18,11 +19,13 @@ import { useHandleUiEvents } from './useHandleUiEvent'
export const SAVE_FILE_COPY_ACTION = 'save-file-copy' export const SAVE_FILE_COPY_ACTION = 'save-file-copy'
export const OPEN_FILE_ACTION = 'open-file' export const OPEN_FILE_ACTION = 'open-file'
export const NEW_PROJECT_ACTION = 'new-file' export const NEW_PROJECT_ACTION = 'new-file'
export const NEW_SHARED_PROJECT_ACTION = 'new-shared-file'
const saveFileNames = new WeakMap<TLStore, string>() const saveFileNames = new WeakMap<TLStore, string>()
export function useFileSystem({ isMultiplayer }: { isMultiplayer: boolean }): TLUiOverrides { export function useFileSystem({ isMultiplayer }: { isMultiplayer: boolean }): TLUiOverrides {
const handleUiEvent = useHandleUiEvents() const handleUiEvent = useHandleUiEvents()
const navigate = useNavigate()
return useMemo((): TLUiOverrides => { return useMemo((): TLUiOverrides => {
return { return {
@ -67,6 +70,15 @@ export function useFileSystem({ isMultiplayer }: { isMultiplayer: boolean }): TL
await parseAndLoadDocument(editor, await file.text(), msg, addToast) await parseAndLoadDocument(editor, await file.text(), msg, addToast)
}, },
} }
actions[NEW_SHARED_PROJECT_ACTION] = {
id: NEW_SHARED_PROJECT_ACTION,
label: 'action.new-shared-project',
readonlyOk: true,
async onSelect(source) {
handleUiEvent('create-new-shared-project', { source })
navigate('/new')
},
}
actions[NEW_PROJECT_ACTION] = { actions[NEW_PROJECT_ACTION] = {
id: NEW_PROJECT_ACTION, id: NEW_PROJECT_ACTION,
label: 'action.new-project', label: 'action.new-project',
@ -93,7 +105,7 @@ export function useFileSystem({ isMultiplayer }: { isMultiplayer: boolean }): TL
return actions return actions
}, },
} }
}, [isMultiplayer, handleUiEvent]) }, [handleUiEvent, isMultiplayer, navigate])
} }
export function getSaveFileCopyAction( export function getSaveFileCopyAction(