102 lines
2.6 KiB
JavaScript
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)
|