share project and current page

This commit is contained in:
Judicael 2022-08-18 08:11:26 +03:00
parent f6073f3021
commit 5eb3dfc204
5 changed files with 130 additions and 52 deletions

View file

@ -375,9 +375,13 @@ const InnerTldraw = React.memo(function InnerTldraw({
React.useEffect(() => {
if (decodedPage.length) {
const state = JSON.parse(decodedPage) as Record<'page' | 'pageState', any>
const state = JSON.parse(decodedPage) as Record<string, any>
if (Object.keys(state).length) {
app.pastePageContent(state.page, state.pageState)
if ('page' in state) {
app.loadDocumentFromURL(undefined, state.page, state.pageState)
} else {
app.loadDocumentFromURL(state as TDDocument)
}
}
}
}, [decodedPage])

View file

@ -1,6 +1,11 @@
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
import { ClipboardIcon } from '@radix-ui/react-icons'
import JSONCrush from 'jsoncrush'
import * as React from 'react'
import { FormattedMessage } from 'react-intl'
import { DMContent, DMItem } from '~components/Primitives/DropdownMenu'
import { Panel } from '~components/Primitives/Panel'
import { SmallIcon } from '~components/Primitives/SmallIcon'
import { ToolButton } from '~components/Primitives/ToolButton'
import { UndoIcon } from '~components/Primitives/icons'
import { useTldrawApp } from '~hooks'
@ -29,27 +34,6 @@ export function TopPanel({
showMultiplayerMenu,
}: TopPanelProps) {
const app = useTldrawApp()
const currentPageId = app.appState.currentPageId
const pageDocument = app.document.pages[currentPageId]
const pageState = app.document.pageStates[currentPageId]
const copyShareableLink = () => {
try {
const state = {
page: {
...pageDocument,
},
pageState: {
...pageState,
},
}
const crushed = JSONCrush.crush(JSON.stringify(state))
const link = `${window.location.href}/?d=${encodeURIComponent(crushed)}`
navigator.clipboard.writeText(link)
} catch (err) {
console.error(err)
}
}
return (
<StyledTopPanel>
@ -63,7 +47,7 @@ export function TopPanel({
<StyledSpacer />
{(showStyles || showZoom) && (
<Panel side="right">
<ShareButton onClick={copyShareableLink}>Share page</ShareButton>
<ShareMenu />
{app.readOnly ? (
<ReadOnlyLabel>Read Only</ReadOnlyLabel>
) : (
@ -115,7 +99,7 @@ const ReadOnlyLabel = styled('div', {
userSelect: 'none',
})
const ShareButton = styled('button', {
const ShareButton = styled(DropdownMenu.Trigger, {
all: 'unset',
display: 'inline-flex',
alignItems: 'center',
@ -132,3 +116,71 @@ const ShareButton = styled('button', {
color: 'White',
marginTop: 2,
})
const ShareMenu = () => {
const app = useTldrawApp()
const currentPageId = app.appState.currentPageId
const pageDocument = app.document.pages[currentPageId]
const pageState = app.document.pageStates[currentPageId]
const copyCurrentPageLink = () => {
const hasAsset = Object.entries(pageDocument.shapes).filter(
([_, value]) => value.assetId
).length
if (hasAsset) {
alert('too big to fit in an url')
} else {
try {
const state = {
page: {
...pageDocument,
},
pageState: {
...pageState,
},
}
const crushed = JSONCrush.crush(JSON.stringify(state))
const link = `${window.location.href}/?d=${encodeURIComponent(crushed)}`
navigator.clipboard.writeText(link)
} catch (err) {
console.error(err)
}
}
}
const copyProjectLink = () => {
if (Object.keys(app.document.assets).length) {
alert('too big to fit in an url')
} else {
try {
const crushed = JSONCrush.crush(JSON.stringify(app.document))
const link = `${window.location.href}/?d=${encodeURIComponent(crushed)}`
navigator.clipboard.writeText(link)
} catch (e) {
console.error(e)
}
}
}
return (
<DropdownMenu.Root dir="ltr">
<ShareButton id="TD-MultiplayerMenuIcon">
<FormattedMessage id="share" />
</ShareButton>
<DMContent variant="menu" id="TD-MultiplayerMenu" side="bottom" align="start" sideOffset={4}>
<DMItem id="TD-Multiplayer-CopyInviteLink" onClick={copyCurrentPageLink}>
<FormattedMessage id="copy.current.project.link" />
<SmallIcon>
<ClipboardIcon />
</SmallIcon>
</DMItem>
<DMItem id="TD-Multiplayer-CopyReadOnlyLink" onClick={copyProjectLink}>
<FormattedMessage id="copy.project.link" />
<SmallIcon>
<ClipboardIcon />
</SmallIcon>
</DMItem>
</DMContent>
</DropdownMenu.Root>
)
}

View file

@ -1362,6 +1362,7 @@ export class TldrawApp extends StateManager<TDSnapshot> {
* @param document The document to load
*/
loadDocument = (document: TDDocument): this => {
this.setIsLoading(true)
this.selectNone()
this.resetHistory()
this.clearSelectHistory()
@ -1384,10 +1385,26 @@ export class TldrawApp extends StateManager<TDSnapshot> {
this.replaceState(migrate(state, TldrawApp.version), 'loaded_document')
const { point, zoom } = this.camera
this.updateViewport(point, zoom)
this.setIsLoading(false)
return this
}
pastePageContent = (page: TDPage, pageState: Record<string, TLPageState>): this => {
/**
* load content from URL
* @param document
* @param page
* @param pageState
* @returns
*/
loadDocumentFromURL = (
document?: TDDocument,
page?: TDPage,
pageState?: Record<string, TLPageState>
): this => {
if (document) {
return this.loadDocument(document)
} else {
this.setIsLoading(true)
const { currentPageId } = this
const state = {
id: 'create_page',
@ -1397,29 +1414,31 @@ export class TldrawApp extends StateManager<TDSnapshot> {
},
document: {
pages: {
[page.id]: undefined,
[page!.id]: undefined,
},
pageStates: {
[page.id]: undefined,
[page!.id]: undefined,
},
},
},
after: {
appState: {
currentPageId: page.id,
currentPageId: page!.id,
},
document: {
pages: {
[page.id]: page,
[page!.id]: page,
},
pageStates: {
[page.id]: pageState,
[page!.id]: pageState,
},
},
},
}
this.setIsLoading(false)
return this.setState(state)
}
}
// Should we move this to the app layer? onSave, onSaveAs, etc?

View file

@ -406,6 +406,7 @@ TldrawTestApp {
"isPointing": false,
"justSent": false,
"loadDocument": [Function],
"loadDocumentFromURL": [Function],
"loadRoom": [Function],
"mergeDocument": [Function],
"metaKey": false,
@ -485,7 +486,6 @@ TldrawTestApp {
],
"pan": [Function],
"paste": [Function],
"pastePageContent": [Function],
"patchCreate": [Function],
"patchState": [Function],
"persist": [Function],

View file

@ -117,5 +117,8 @@
"distribute.x": "Distribute Horizontal",
"distribute.y": "Distribute Vertical",
"stretch.x": "Stretch Horizontal",
"stretch.y": "Stretch Vertical"
"stretch.y": "Stretch Vertical",
"share": "Share",
"copy.current.page.link": "Copy Current Page Link",
"copy.project.link": "Copy Project Link"
}