Open share menu when navigating from create new shared project button (#3898)

This PR ensures that the share menu is open when navigating from the
create new shared project button.

This could be achieved by calling ```editor.addOpenMenu('share-menu')```
after ```navigate('/new')``` , but that opens the menu on the local
editor first so you get a flash of that before the multiplayer editor
loads.

Instead I've used the state prop on the Navigate component/function to
pass a property called shouldOpenShareMenu.

If the user presses the back button to return to the local editor
instance then the open state of the share menu is preserved, which is
actually something we don't want in this case. Not sure how to deal with
that without adding a ton more complexity, is it worth it?

### 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
- [ ] `feature` — New feature
- [x] `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. Click create new shared project from the file menu
2. Share menu should open after navigating to the new room

### Release Notes

- Open share menu when navigating from the create new shared project
button.

---------

Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This commit is contained in:
Taha 2024-06-10 09:15:55 +01:00 committed by GitHub
parent 6745f2cbcf
commit 4dab25be57
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 29 additions and 29 deletions

View file

@ -21,8 +21,6 @@ import { createQRCodeImageDataString } from '../utils/qrcode'
import { SHARE_PROJECT_ACTION, SHARE_SNAPSHOT_ACTION } from '../utils/sharing' import { SHARE_PROJECT_ACTION, SHARE_SNAPSHOT_ACTION } from '../utils/sharing'
import { ShareButton } from './ShareButton' import { ShareButton } from './ShareButton'
const COPY_LINK_TIMEOUT = 1000
const SHARE_CURRENT_STATE = { const SHARE_CURRENT_STATE = {
OFFLINE: 'offline', OFFLINE: 'offline',
SHARED_READ_WRITE: 'shared-read-write', SHARED_READ_WRITE: 'shared-read-write',
@ -126,9 +124,6 @@ export const ShareMenu = React.memo(function ShareMenu() {
const currentQrCodeUrl = isReadOnlyLink const currentQrCodeUrl = isReadOnlyLink
? shareState.readonlyQrCodeDataUrl ? shareState.readonlyQrCodeDataUrl
: shareState.qrCodeDataUrl : shareState.qrCodeDataUrl
const [didCopy, setDidCopy] = useState(false)
const [didCopyReadonlyLink, setDidCopyReadonlyLink] = useState(false)
const [didCopySnapshotLink, setDidCopySnapshotLink] = useState(false)
const toasts = useToasts() const toasts = useToasts()
useEffect(() => { useEffect(() => {
@ -207,8 +202,6 @@ export const ShareMenu = React.memo(function ShareMenu() {
)} )}
onClick={() => { onClick={() => {
if (!currentShareLinkUrl) return if (!currentShareLinkUrl) return
setDidCopy(true)
setTimeout(() => setDidCopy(false), COPY_LINK_TIMEOUT)
navigator.clipboard.writeText(currentShareLinkUrl) navigator.clipboard.writeText(currentShareLinkUrl)
toasts.addToast({ toasts.addToast({
title: msg('share-menu.copied'), title: msg('share-menu.copied'),
@ -221,13 +214,11 @@ export const ShareMenu = React.memo(function ShareMenu() {
{shareState.state === SHARE_CURRENT_STATE.SHARED_READ_WRITE && ( {shareState.state === SHARE_CURRENT_STATE.SHARED_READ_WRITE && (
<TldrawUiMenuItem <TldrawUiMenuItem
id="copy-to-clipboard" id="copy-to-clipboard"
readonlyOk readonlyOk={false}
icon={didCopy ? 'clipboard-copied' : 'clipboard-copy'}
label="share-menu.copy-link" label="share-menu.copy-link"
icon="clipboard-copy"
onSelect={() => { onSelect={() => {
if (!shareState.url) return if (!shareState.url) return
setDidCopy(true)
setTimeout(() => setDidCopy(false), COPY_LINK_TIMEOUT)
navigator.clipboard.writeText(shareState.url) navigator.clipboard.writeText(shareState.url)
toasts.addToast({ toasts.addToast({
title: msg('share-menu.copied'), title: msg('share-menu.copied'),
@ -239,12 +230,10 @@ export const ShareMenu = React.memo(function ShareMenu() {
<TldrawUiMenuItem <TldrawUiMenuItem
id="copy-readonly-to-clipboard" id="copy-readonly-to-clipboard"
readonlyOk readonlyOk
icon={didCopyReadonlyLink ? 'clipboard-copied' : 'clipboard-copy'}
label="share-menu.copy-readonly-link" label="share-menu.copy-readonly-link"
icon="clipboard-copy"
onSelect={() => { onSelect={() => {
if (!shareState.readonlyUrl) return if (!shareState.readonlyUrl) return
setDidCopyReadonlyLink(true)
setTimeout(() => setDidCopyReadonlyLink(false), COPY_LINK_TIMEOUT)
navigator.clipboard.writeText(shareState.readonlyUrl) navigator.clipboard.writeText(shareState.readonlyUrl)
toasts.addToast({ toasts.addToast({
title: msg('share-menu.copied'), title: msg('share-menu.copied'),
@ -260,13 +249,11 @@ export const ShareMenu = React.memo(function ShareMenu() {
<TldrawUiMenuGroup id="snapshot"> <TldrawUiMenuGroup id="snapshot">
<TldrawUiMenuItem <TldrawUiMenuItem
{...shareSnapshot} {...shareSnapshot}
icon={didCopySnapshotLink ? 'clipboard-copied' : 'clipboard-copy'} icon="clipboard-copy"
onSelect={async () => { onSelect={async () => {
setIsUploadingSnapshot(true) setIsUploadingSnapshot(true)
await shareSnapshot.onSelect('share-menu') await shareSnapshot.onSelect('share-menu')
setIsUploadingSnapshot(false) setIsUploadingSnapshot(false)
setDidCopySnapshotLink(true)
setTimeout(() => setDidCopySnapshotLink(false), COPY_LINK_TIMEOUT)
}} }}
spinner={isUploadingSnapshot} spinner={isUploadingSnapshot}
/> />
@ -306,14 +293,12 @@ export const ShareMenu = React.memo(function ShareMenu() {
<TldrawUiMenuItem <TldrawUiMenuItem
id="copy-snapshot-link" id="copy-snapshot-link"
readonlyOk readonlyOk
icon={didCopySnapshotLink ? 'clipboard-copied' : 'clipboard-copy'} icon="clipboard-copy"
label={unwrapLabel(shareSnapshot.label)} label={unwrapLabel(shareSnapshot.label)}
onSelect={async () => { onSelect={async () => {
setIsUploadingSnapshot(true) setIsUploadingSnapshot(true)
await shareSnapshot.onSelect('share-menu') await shareSnapshot.onSelect('share-menu')
setIsUploadingSnapshot(false) setIsUploadingSnapshot(false)
setDidCopySnapshotLink(true)
setTimeout(() => setDidCopySnapshotLink(false), COPY_LINK_TIMEOUT)
}} }}
spinner={isUploadingSnapshot} spinner={isUploadingSnapshot}
/> />

View file

@ -1,4 +1,5 @@
import { useEffect, useRef } from 'react' import { useEffect, useRef } from 'react'
import { useLocation } from 'react-router-dom'
import { atom, useMenuIsOpen, useValue } from 'tldraw' import { atom, useMenuIsOpen, useValue } from 'tldraw'
// When people click the 'create shared project' in the share menu we want to make sure that // When people click the 'create shared project' in the share menu we want to make sure that
@ -12,17 +13,22 @@ export function useShareMenuIsOpen() {
const isOpen = useValue('is menu open', () => persistentShareMenuOpenAtom.get(), []) const isOpen = useValue('is menu open', () => persistentShareMenuOpenAtom.get(), [])
const [isShareMenuOpen, onOpenChange] = useMenuIsOpen('share menu') const [isShareMenuOpen, onOpenChange] = useMenuIsOpen('share menu')
// on initial render the persistent option takes effect // on initial render the persistent option takes effect
const location = useLocation()
const isFirst = useRef(true) const isFirst = useRef(true)
useEffect(() => { useEffect(() => {
if (isFirst.current) { if (isFirst.current) {
isFirst.current = false isFirst.current = false
if (location.state?.shouldOpenShareMenu) {
// if we are navigating from the new shared project button then
// we always open the share menu
persistentShareMenuOpenAtom.set(true)
}
onOpenChange(persistentShareMenuOpenAtom.get()) onOpenChange(persistentShareMenuOpenAtom.get())
} else { } else {
persistentShareMenuOpenAtom.set(isShareMenuOpen) persistentShareMenuOpenAtom.set(isShareMenuOpen)
} }
}, [isShareMenuOpen, onOpenChange]) }, [isShareMenuOpen, location.state, onOpenChange])
return [isOpen, onOpenChange] as const return [isOpen, onOpenChange] as const
} }

View file

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

View file

@ -256,18 +256,18 @@
"share-menu.fork-note": "Create a new shared project based on this snapshot.", "share-menu.fork-note": "Create a new shared project based on this snapshot.",
"share-menu.share-project": "Share this project", "share-menu.share-project": "Share this project",
"share-menu.default-project-name": "Shared Project", "share-menu.default-project-name": "Shared Project",
"share-menu.copy-link": "Copy share link", "share-menu.copy-link": "Copy editor link",
"share-menu.readonly-link": "Read-only", "share-menu.readonly-link": "Read-only",
"share-menu.create-snapshot-link": "Copy snapshot link", "share-menu.create-snapshot-link": "Copy snapshot link",
"share-menu.snapshot-link-note": "Capture and share this project as a read-only snapshot link.", "share-menu.snapshot-link-note": "Capture and share this project as a read-only snapshot link.",
"share-menu.copy-readonly-link": "Copy read-only link", "share-menu.copy-readonly-link": "Copy viewer link",
"share-menu.offline-note": "Create a new shared project based on your current project.", "share-menu.offline-note": "Create a new shared project based on your current project.",
"share-menu.copy-link-note": "Anyone with the link will be able to view and edit this project.", "share-menu.copy-link-note": "Anyone with the link will be able to view and edit this project.",
"share-menu.copy-readonly-link-note": "Anyone with the link will be able to access this project.", "share-menu.copy-readonly-link-note": "Anyone with the link will be able to access this project.",
"share-menu.project-too-large": "Sorry, this project can't be shared because it's too large. We're working on it!", "share-menu.project-too-large": "Sorry, this project can't be shared because it's too large. We're working on it!",
"share-menu.upload-failed": "Sorry, we couldn't upload your project at the moment. Please try again or let us know if the problem persists.", "share-menu.upload-failed": "Sorry, we couldn't upload your project at the moment. Please try again or let us know if the problem persists.",
"share-menu.creating-project": "Creating the new project…", "share-menu.creating-project": "Creating the new project…",
"share-menu.copied": "Copied link!", "share-menu.copied": "Copied link",
"status.offline": "Offline", "status.offline": "Offline",
"status.online": "Online", "status.online": "Online",
"people-menu.title": "People", "people-menu.title": "People",

View file

@ -260,11 +260,11 @@ export const DEFAULT_TRANSLATION = {
'share-menu.fork-note': 'Create a new shared project based on this snapshot.', 'share-menu.fork-note': 'Create a new shared project based on this snapshot.',
'share-menu.share-project': 'Share this project', 'share-menu.share-project': 'Share this project',
'share-menu.default-project-name': 'Shared Project', 'share-menu.default-project-name': 'Shared Project',
'share-menu.copy-link': 'Copy share link', 'share-menu.copy-link': 'Copy editor link',
'share-menu.readonly-link': 'Read-only', 'share-menu.readonly-link': 'Read-only',
'share-menu.create-snapshot-link': 'Copy snapshot link', 'share-menu.create-snapshot-link': 'Copy snapshot link',
'share-menu.snapshot-link-note': 'Capture and share this project as a read-only snapshot link.', 'share-menu.snapshot-link-note': 'Capture and share this project as a read-only snapshot link.',
'share-menu.copy-readonly-link': 'Copy read-only link', 'share-menu.copy-readonly-link': 'Copy viewer link',
'share-menu.offline-note': 'Create a new shared project based on your current project.', 'share-menu.offline-note': 'Create a new shared project based on your current project.',
'share-menu.copy-link-note': 'Anyone with the link will be able to view and edit this project.', 'share-menu.copy-link-note': 'Anyone with the link will be able to view and edit this project.',
'share-menu.copy-readonly-link-note': 'Anyone with the link will be able to access this project.', 'share-menu.copy-readonly-link-note': 'Anyone with the link will be able to access this project.',
@ -273,7 +273,7 @@ export const DEFAULT_TRANSLATION = {
'share-menu.upload-failed': 'share-menu.upload-failed':
"Sorry, we couldn't upload your project at the moment. Please try again or let us know if the problem persists.", "Sorry, we couldn't upload your project at the moment. Please try again or let us know if the problem persists.",
'share-menu.creating-project': 'Creating the new project…', 'share-menu.creating-project': 'Creating the new project…',
'share-menu.copied': 'Copied link!', 'share-menu.copied': 'Copied link',
'status.offline': 'Offline', 'status.offline': 'Offline',
'status.online': 'Online', 'status.online': 'Online',
'people-menu.title': 'People', 'people-menu.title': 'People',