imageElement.tsx
TLDR
This file, located at webapp/src/components/content/imageElement.tsx
, contains the ImageElement
component. This component is responsible for rendering an image block in the content area of the application. The component fetches image data from the server and displays it on the page. It also handles the creation of a new image block and uploads the selected image file to the server.
Methods
ImageElement
This method is the main component that renders the image block. It takes a block
prop which contains the content block data and displays the image associated with it. If the image is archived, it renders an ArchivedFile
component. If the image data is not available yet, it returns null
.
loadImage
This method is an asynchronous function that loads the image data from the server. It is called inside the useEffect
hook of the ImageElement
component. It uses the octoClient
to fetch the image data as a data URL and sets it using the setImageDataUrl
and setFileInfo
hooks.
contentRegistry.registerContentType
This method registers the image
content type with the contentRegistry
. It provides the display text, icon, and the necessary functions to create a new image block and render the ImageElement
component.
Classes
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useEffect, useState} from 'react'
import {IntlShape} from 'react-intl'
import {ContentBlock} from '../../blocks/contentBlock'
import {ImageBlock, createImageBlock} from '../../blocks/imageBlock'
import octoClient from '../../octoClient'
import {Utils} from '../../utils'
import ImageIcon from '../../widgets/icons/image'
import {sendFlashMessage} from '../../components/flashMessages'
import {FileInfo} from '../../blocks/block'
import {contentRegistry} from './contentRegistry'
import ArchivedFile from './archivedFile/archivedFile'
type Props = {
block: ContentBlock
}
const ImageElement = (props: Props): JSX.Element|null => {
const [imageDataUrl, setImageDataUrl] = useState<string|null>(null)
const [fileInfo, setFileInfo] = useState<FileInfo>({})
const {block} = props
useEffect(() => {
if (!imageDataUrl) {
const loadImage = async () => {
const fileURL = await octoClient.getFileAsDataUrl(block.boardId, props.block.fields.fileId)
setImageDataUrl(fileURL.url || '')
setFileInfo(fileURL)
}
loadImage()
}
}, [])
if (fileInfo.archived) {
return (
<ArchivedFile fileInfo={fileInfo}/>
)
}
if (!imageDataUrl) {
return null
}
return (
<img
className='ImageElement'
src={imageDataUrl}
alt={block.title}
/>
)
}
contentRegistry.registerContentType({
type: 'image',
getDisplayText: (intl: IntlShape) => intl.formatMessage({id: 'ContentBlock.image', defaultMessage: 'image'}),
getIcon: () => <ImageIcon/>,
createBlock: async (boardId: string, intl: IntlShape) => {
return new Promise<ImageBlock>(
(resolve) => {
Utils.selectLocalFile(async (file) => {
const fileId = await octoClient.uploadFile(boardId, file)
if (fileId) {
const block = createImageBlock()
block.fields.fileId = fileId || ''
resolve(block)
} else {
sendFlashMessage({content: intl.formatMessage({id: 'createImageBlock.failed', defaultMessage: 'Unable to upload the file. File size limit reached.'}), severity: 'normal'})
}
},
'.jpg,.jpeg,.png,.gif')
},
)
// return new ImageBlock()
},
createComponent: (block) => <ImageElement block={block}/>,
})
export default React.memo(ImageElement)