102 lines
2.6 KiB
JavaScript

import PropTypes from 'prop-types'
import { ApiServerContext } from '../context/ApiServerContext'
import { useCallback, useContext, useEffect, useState, memo } from 'react'
import LoadingPlaceholder from './LoadingPlaceholder'
import GCodePreview from './GCodePreview'
import ThreeDPreview from './ThreeDPreview'
import { AuthContext } from '../context/AuthContext'
const FilePreview = ({ file, style = {} }) => {
const { token } = useContext(AuthContext)
const { fetchFileContent } = useContext(ApiServerContext)
const [fileObjectUrl, setFileObjectUrl] = useState(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
const fetchPreview = useCallback(async () => {
if (error != null) {
return
}
setLoading(true)
console.log('fetching file content', file)
const objectUrl = await fetchFileContent(file, false)
if (objectUrl == null) {
setLoading(false)
console.error('Failed to fetch file content', file)
setError('Failed to fetch file content')
return
}
setFileObjectUrl(objectUrl)
setLoading(false)
}, [file, fetchFileContent])
useEffect(() => {
if (file?.type && token != null) {
fetchPreview()
}
}, [file._id, file?.type, fetchPreview, token])
if (loading == true || !file?.type) {
return <LoadingPlaceholder message={'Loading file preview...'} />
}
if (error != null) {
return <div style={{ color: 'red' }}>{error}</div>
}
const isGcode = ['.g', '.gcode'].includes(
(file?.extension || '').toLowerCase()
)
const is3DModel = ['.stl', '.3mf'].includes(
(file?.extension || '').toLowerCase()
)
const isImage = file?.type.startsWith('image/')
if (isGcode && fileObjectUrl) {
return (
<GCodePreview
src={fileObjectUrl}
topLayerColor={'#ff9800'}
lastSegmentColor={'#e91e63'}
startLayer={0}
endLayer={undefined}
lineWidth={1}
style={style}
/>
)
}
if (is3DModel && fileObjectUrl) {
return (
<ThreeDPreview
src={fileObjectUrl}
style={style}
extension={file.extension}
/>
)
}
if (isImage && fileObjectUrl) {
return <img src={fileObjectUrl} style={style}></img>
}
return null
}
FilePreview.propTypes = {
file: PropTypes.object.isRequired,
style: PropTypes.object
}
// Custom comparison function to only re-render when file._id changes
const areEqual = (prevProps, nextProps) => {
return (
prevProps.file?._id === nextProps.file?._id &&
JSON.stringify(prevProps.style) === JSON.stringify(nextProps.style)
)
}
export default memo(FilePreview, areEqual)