remove safari special-casing for paste (#1470)

Previously, we had a bunch of special-casing around paste to support
safari quirks on desktop and ios.

Since upgrading radix-ui and useGesture, these are no longer needed and
were actually causing issues. This diff removes the special casing for
paste and makes it a normal action that get triggered the same way as
any other.

### Change Type
- [x] `patch` — Bug Fix

### Test Plan

1. Copy text outside of tldraw, paste in tldraw with the context menu,
edit menu, and keyboard shortcut
2. Repeat for images outside of tldraw
3. Repeat for shapes inside of tldraw

### Release Notes

[fixes a regression introduced during this release]
This commit is contained in:
alex 2023-05-26 09:24:21 +01:00 committed by GitHub
parent 042edeb4b4
commit f8b6ee6ab9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 30 additions and 101 deletions

View file

@ -1025,10 +1025,10 @@ export function useLanguages(): {
export function useLocalStorageState<T = any>(key: string, defaultValue: T): readonly [T, (setter: ((value: T) => T) | T) => void];
// @public (undocumented)
export function useMenuClipboardEvents(source: TLUiEventSource): {
copy: () => void;
cut: () => void;
paste: (data: ClipboardItem[] | DataTransfer, point?: VecLike) => Promise<void>;
export function useMenuClipboardEvents(): {
copy: (source: TLUiEventSource) => void;
cut: (source: TLUiEventSource) => void;
paste: (data: ClipboardItem[] | DataTransfer, source: TLUiEventSource, point?: VecLike) => Promise<void>;
};
// @public (undocumented)

View file

@ -5,7 +5,6 @@ import * as React from 'react'
import { useValue } from 'signia-react'
import { MenuChild } from '../hooks/menuHelpers'
import { useBreakpoint } from '../hooks/useBreakpoint'
import { useMenuClipboardEvents } from '../hooks/useClipboardEvents'
import { useContextMenuSchema } from '../hooks/useContextMenuSchema'
import { useMenuIsOpen } from '../hooks/useMenuIsOpen'
import { useReadonly } from '../hooks/useReadonly'
@ -61,7 +60,6 @@ function ContextMenuContent() {
const [_, handleSubOpenChange] = useMenuIsOpen('context menu sub')
const isReadonly = useReadonly()
const { paste } = useMenuClipboardEvents('context-menu')
const breakpoint = useBreakpoint()
const container = useContainer()
@ -73,42 +71,6 @@ function ContextMenuContent() {
switch (item.type) {
case 'custom': {
switch (item.id) {
case 'MENU_PASTE': {
return (
<_ContextMenu.Item key={item.id}>
<Button
className="tlui-menu__button"
data-wd={`menu-item.${item.id}`}
kbd="$v"
label="action.paste"
disabled={item.disabled}
onClick={() => {
if (!app.isSafari || (app.isSafari && app.isIos)) {
navigator.clipboard.read().then((clipboardItems) => {
paste(clipboardItems, app.inputs.currentPagePoint)
})
}
}}
onMouseDown={() => {
if (app.isSafari && !app.isIos) {
// NOTE: This must be a onMouseDown for Safari/desktop, onClick doesn't work at the time of writing... 😒
navigator.clipboard.read().then((clipboardItems) => {
paste(clipboardItems, app.inputs.currentPagePoint)
})
}
}}
// onPointerUp={() => {
// if (app.isSafari && app.isIos) {
// // NOTE: This must be a onPointerUp for Safari/mobile, onClick doesn't work at the time of writing... 😒
// navigator.clipboard.read().then((clipboardItems) => {
// paste(clipboardItems, app.inputs.currentPagePoint)
// })
// }
// }}
/>
</_ContextMenu.Item>
)
}
case 'MOVE_TO_PAGE_MENU': {
return <MoveToPageMenu key={item.id} />
}

View file

@ -1,8 +1,7 @@
import { App, preventDefault, useApp } from '@tldraw/editor'
import { App, useApp } from '@tldraw/editor'
import * as React from 'react'
import { MenuChild } from '../hooks/menuHelpers'
import { useBreakpoint } from '../hooks/useBreakpoint'
import { useMenuClipboardEvents } from '../hooks/useClipboardEvents'
import { useMenuSchema } from '../hooks/useMenuSchema'
import { useReadonly } from '../hooks/useReadonly'
import { useTranslation } from '../hooks/useTranslation/useTranslation'
@ -37,7 +36,6 @@ function MenuContent() {
const menuSchema = useMenuSchema()
const breakpoint = useBreakpoint()
const isReadonly = useReadonly()
const { paste } = useMenuClipboardEvents('menu')
function getMenuItem(app: App, item: MenuChild, parent: MenuChild | null, depth: number) {
switch (item.type) {
@ -48,35 +46,6 @@ function MenuContent() {
return <LanguageMenu key="item" />
}
if (item.id === 'MENU_PASTE') {
return (
<M.Item
key={item.id}
data-wd={`menu-item.${item.id}`}
kbd="$v"
label="action.paste"
disabled={item.disabled}
onMouseDown={() => {
if (app.isSafari && navigator.clipboard?.read) {
// NOTE: This must be a onMouseDown for Safari/desktop, onClick doesn't work at the time of writing...
navigator.clipboard.read().then((clipboardItems) => {
paste(clipboardItems)
})
}
}}
onClick={() => {
if (app.isSafari) {
// noop
} else if (navigator.clipboard?.read) {
navigator.clipboard.read().then((clipboardItems) => {
paste(clipboardItems)
})
}
}}
onPointerUp={preventDefault}
/>
)
}
return null
}
case 'group': {

View file

@ -64,17 +64,12 @@ function makeActions(actions: ActionItem[]) {
export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
const app = useApp()
// const saveFile = useSaveFile()
// const saveFileAs = useSaveFileAs()
// const newFile = useNewFile()
// const openFile = useOpenFile()
const { addDialog, clearDialogs } = useDialogs()
const { clearToasts } = useToasts()
const insertMedia = useInsertMedia()
const printSelectionOrPages = usePrint()
const { cut, copy } = useMenuClipboardEvents('unknown')
const { cut, copy, paste } = useMenuClipboardEvents()
const copyAs = useCopyAs()
const exportAs = useExportAs()
@ -631,9 +626,8 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
kbd: '$x',
readonlyOk: false,
onSelect(source) {
trackEvent('cut', { source })
app.mark('cut')
cut()
cut(source)
},
},
{
@ -642,8 +636,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
kbd: '$c',
readonlyOk: true,
onSelect(source) {
trackEvent('copy', { source })
copy()
copy(source)
},
},
{
@ -651,9 +644,14 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
label: 'action.paste',
kbd: '$v',
readonlyOk: false,
onSelect() {
// must be inlined with a custom menu item
// the kbd listed here should have no effect
onSelect(source) {
navigator.clipboard?.read().then((clipboardItems) => {
paste(
clipboardItems,
source,
source === 'context-menu' ? app.inputs.currentPagePoint : undefined
)
})
},
},
{
@ -931,6 +929,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
copyAs,
cut,
copy,
paste,
clearDialogs,
clearToasts,
printSelectionOrPages,

View file

@ -539,33 +539,37 @@ const handleNativeOrMenuCopy = (app: App) => {
}
/** @public */
export function useMenuClipboardEvents(source: TLUiEventSource) {
export function useMenuClipboardEvents() {
const app = useApp()
const trackEvent = useEvents()
const copy = useCallback(
function onCopy() {
function onCopy(source: TLUiEventSource) {
if (app.selectedIds.length === 0) return
handleNativeOrMenuCopy(app)
trackEvent('copy', { source })
},
[app, trackEvent, source]
[app, trackEvent]
)
const cut = useCallback(
function onCut() {
function onCut(source: TLUiEventSource) {
if (app.selectedIds.length === 0) return
handleNativeOrMenuCopy(app)
app.deleteShapes()
trackEvent('cut', { source })
},
[app, trackEvent, source]
[app, trackEvent]
)
const paste = useCallback(
async function onPaste(data: DataTransfer | ClipboardItem[], point?: VecLike) {
async function onPaste(
data: DataTransfer | ClipboardItem[],
source: TLUiEventSource,
point?: VecLike
) {
// If we're editing a shape, or we are focusing an editable input, then
// we would want the user's paste interaction to go to that element or
// input instead; e.g. when pasting text into a text shape's content
@ -577,7 +581,7 @@ export function useMenuClipboardEvents(source: TLUiEventSource) {
} else {
// Read it first and then recurse, kind of weird
navigator.clipboard.read().then((clipboardItems) => {
paste(clipboardItems, app.inputs.currentPagePoint)
paste(clipboardItems, source, point)
})
}
},

View file

@ -163,7 +163,7 @@ export const ContextMenuSchemaProvider = track(function ContextMenuSchemaProvide
'clipboard-group',
oneSelected && menuItem(actions['cut']),
oneSelected && menuItem(actions['copy']),
showMenuPaste && menuCustom('MENU_PASTE', { readonlyOk: false })
showMenuPaste && menuItem(actions['paste'])
),
atLeastOneShapeOnPage &&
menuGroup(

View file

@ -97,12 +97,7 @@ export function MenuSchemaProvider({ overrides, children }: MenuSchemaProviderPr
'clipboard-actions',
menuItem(actions['cut'], { disabled: noneSelected }),
menuItem(actions['copy'], { disabled: noneSelected }),
{
id: 'MENU_PASTE',
type: 'custom',
disabled: !showMenuPaste,
readonlyOk: false,
}
menuItem(actions['paste'], { disabled: !showMenuPaste })
),
menuGroup(
'conversions',