imagePaste.tsx
TLDR
This file, imagePaste.tsx
, is a React component that handles image pasting and dragging and dropping images into a board.
Methods
useImagePaste
This is the main function of the file that handles image pasting and dragging and dropping images into a board. It takes three parameters: boardId
(the ID of the board), cardId
(the ID of the card), and contentOrder
(an array representing the order of content in the card). This function performs the following tasks:
- Handles the
paste
event and uploads pasted images to the board. - Handles the
drop
event and uploads dropped images to the board. - Adds event listeners for
paste
anddrop
events. - Removes event listeners when the component is unmounted.
Classes
None
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {useEffect, useCallback} from 'react'
import {useIntl} from 'react-intl'
import {ImageBlock, createImageBlock} from '../../blocks/imageBlock'
import {sendFlashMessage} from '../flashMessages'
import {Block} from '../../blocks/block'
import octoClient from '../../octoClient'
import mutator from '../../mutator'
export default function useImagePaste(boardId: string, cardId: string, contentOrder: Array<string | string[]>): void {
const intl = useIntl()
const uploadItems = useCallback(async (items: FileList) => {
let newImage: File|null = null
const uploads: Array<Promise<string|undefined>> = []
if (!items.length) {
return
}
for (const item of items) {
newImage = item
if (newImage?.type.indexOf('image/') === 0) {
uploads.push(octoClient.uploadFile(boardId, newImage))
}
}
const uploaded = await Promise.all(uploads)
const blocksToInsert: ImageBlock[] = []
let someFilesNotUploaded = false
for (const fileId of uploaded) {
if (!fileId) {
someFilesNotUploaded = true
continue
}
const block = createImageBlock()
block.parentId = cardId
block.boardId = boardId
block.fields.fileId = fileId || ''
blocksToInsert.push(block)
}
if (someFilesNotUploaded) {
sendFlashMessage({content: intl.formatMessage({id: 'imagePaste.upload-failed', defaultMessage: 'Some files not uploaded. File size limit reached'}), severity: 'normal'})
}
const afterRedo = async (newBlocks: Block[]) => {
const newContentOrder = JSON.parse(JSON.stringify(contentOrder))
newContentOrder.push(...newBlocks.map((b: Block) => b.id))
await octoClient.patchBlock(boardId, cardId, {updatedFields: {contentOrder: newContentOrder}})
}
const beforeUndo = async () => {
const newContentOrder = JSON.parse(JSON.stringify(contentOrder))
await octoClient.patchBlock(boardId, cardId, {updatedFields: {contentOrder: newContentOrder}})
}
await mutator.insertBlocks(boardId, blocksToInsert, 'pasted images', afterRedo, beforeUndo)
}, [cardId, contentOrder, boardId])
const onDrop = useCallback((event: DragEvent): void => {
if (event.dataTransfer) {
const items = event.dataTransfer.files
uploadItems(items)
}
}, [uploadItems])
const onPaste = useCallback((event: ClipboardEvent): void => {
if (event.clipboardData) {
const items = event.clipboardData.files
uploadItems(items)
}
}, [uploadItems])
useEffect(() => {
document.addEventListener('paste', onPaste)
document.addEventListener('drop', onDrop)
return () => {
document.removeEventListener('paste', onPaste)
document.removeEventListener('drop', onDrop)
}
}, [uploadItems, onPaste, onDrop])
}