Files
bee-dashboard/src/pages/files/UploadArea.tsx
T
Bálint Ujvári 0d5138f5bc Fix: file-manager and swarm-desktop bugs (#714)
- drive capacity display with stamp polling
- download/upload progress handling
- overlay and tooltip issues
- FileMaganger readme
- ultra-light mode handling
- account feed view page
- download media files
- remove not found syncing link
- fix ultra light node wallet page
- tooltip issues
---------
Co-authored-by: Andrei Mitrea <andrei.mitrea.hq@gmail.com>
Co-authored-by: nidishk <nidishkrishnan45@gmail.com>
Co-authored-by: Ferenc Sárai <sarai.ferenc@gmail.com>
Co-authored-by: Nándor Komlódi <nandor.komlodi@gmail.com>
Co-authored-by: rolandlor <33499567+rolandlor@users.noreply.github.com>
2026-01-26 12:57:14 +01:00

176 lines
5.3 KiB
TypeScript

import { createStyles, makeStyles, Theme } from '@material-ui/core'
import { DropzoneArea } from 'material-ui-dropzone'
import { useSnackbar } from 'notistack'
import { ReactElement, useContext, useState } from 'react'
import PlusCircle from 'remixicon-react/AddCircleLineIcon'
import FilePlus from 'remixicon-react/FileAddLineIcon'
import FolderPlus from 'remixicon-react/FolderAddLineIcon'
import { useNavigate } from 'react-router-dom'
import { DocumentationText } from '../../components/DocumentationText'
import { SwarmButton } from '../../components/SwarmButton'
import { Context, UploadOrigin } from '../../providers/File'
import { Context as BeeContext } from '../../providers/Bee'
import { ROUTES } from '../../routes'
import { detectIndexHtml } from '../../utils/file'
import { BeeModes } from '@ethersphere/bee-js'
interface Props {
uploadOrigin: UploadOrigin
showHelp: boolean
}
const MAX_FILE_SIZE = 1_000_000_000 // 1 gigabyte
const useStyles = makeStyles((theme: Theme) =>
createStyles({
areaWrapper: { position: 'relative', marginBottom: theme.spacing(2) },
dropzone: {
background: theme.palette.background.default,
outline: 'none',
color: 'transparent',
zIndex: 1,
'& svg': {
opacity: 0,
},
},
buttonWrapper: {
top: '0',
left: '0',
position: 'absolute',
display: 'flex',
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
},
button: {
marginLeft: theme.spacing(0.5),
marginRight: theme.spacing(0.5),
zIndex: 2,
},
}),
)
export function UploadArea({ uploadOrigin, showHelp }: Props): ReactElement {
const { setFiles, setUploadOrigin } = useContext(Context)
const { nodeInfo } = useContext(BeeContext)
const classes = useStyles()
const navigate = useNavigate()
const { enqueueSnackbar } = useSnackbar()
const [strictWebsiteMode, setStrictWebsiteMode] = useState(false)
const [version, setVersion] = useState(0)
const getDropzoneInputDomElement = () => document.querySelector('.MuiDropzoneArea-root input') as HTMLInputElement
const onUploadCollectionClick = () => {
const element = getDropzoneInputDomElement()
if (element) {
element.setAttribute('directory', '')
element.setAttribute('webkitdirectory', '')
element.setAttribute('mozdirectory', '')
element.click()
}
}
const onUploadWebsiteClick = () => {
onUploadCollectionClick()
setStrictWebsiteMode(true)
}
const onUploadFolderClick = () => {
onUploadCollectionClick()
setStrictWebsiteMode(false)
}
const onUploadFileClick = () => {
const element = getDropzoneInputDomElement()
if (element) {
element.removeAttribute('directory')
element.removeAttribute('webkitdirectory')
element.removeAttribute('mozdirectory')
element.click()
}
}
const resetComponentOnAddingInvalidContent = () => {
setTimeout(() => {
setVersion(x => x + 1)
setFiles([])
}, 0)
}
const handleChange = (files?: File[]) => {
if (files) {
const FilePaths = files as FilePath[]
const indexDocument = files.length === 1 ? files[0].name : detectIndexHtml(FilePaths) || undefined
if (files.length && strictWebsiteMode && !indexDocument) {
enqueueSnackbar('To upload a website, there must be an index.html or index.htm in the root of the folder.', {
variant: 'error',
})
resetComponentOnAddingInvalidContent()
return
}
setFiles(FilePaths)
if (files.length) {
setUploadOrigin(uploadOrigin)
navigate(ROUTES.UPLOAD_IN_PROGRESS)
}
}
}
const isUploadEnabled = nodeInfo?.beeMode !== BeeModes.ULTRA_LIGHT
return (
<>
{isUploadEnabled && (
<div className={classes.areaWrapper}>
<DropzoneArea
key={version}
dropzoneClass={classes.dropzone}
onChange={handleChange}
filesLimit={1e9}
maxFileSize={MAX_FILE_SIZE}
showPreviews={false}
/>
<div className={classes.buttonWrapper}>
<SwarmButton className={classes.button} onClick={onUploadFileClick} iconType={FilePlus}>
Add File
</SwarmButton>
<SwarmButton className={classes.button} onClick={onUploadFolderClick} iconType={FolderPlus}>
Add Folder
</SwarmButton>
<SwarmButton className={classes.button} onClick={onUploadWebsiteClick} iconType={PlusCircle}>
Add Website
</SwarmButton>
</div>
</div>
)}
{isUploadEnabled && showHelp && (
<DocumentationText>
You can click the buttons above or simply drag and drop to add a file or folder. To upload a website to Swarm,
make sure that your folder contains an index.html file.
</DocumentationText>
)}
{!isUploadEnabled && (
<DocumentationText>
Uploading files requires running a light node. Please{' '}
<a
href="https://docs.ethswarm.org/docs/desktop/configuration/#upgrading-from-an-ultra-light-to-a-light-node"
target="_blank"
rel="noreferrer"
>
upgrade
</a>{' '}
to continue.
</DocumentationText>
)}
</>
)
}