mirror of https://github.com/kremalicious/ipfs.git
102 lines
2.7 KiB
TypeScript
102 lines
2.7 KiB
TypeScript
import React, { useState, useEffect } from 'react'
|
|
import { ipfsNodeUri, ipfsGateway } from '../../site.config'
|
|
import Dropzone from './Dropzone'
|
|
import styles from './Add.module.css'
|
|
import Spinner from './Spinner'
|
|
import useIpfsApi, { IpfsConfig } from '../hooks/use-ipfs-api'
|
|
|
|
export function formatBytes(a: number, b: number) {
|
|
if (a === 0) return '0 Bytes'
|
|
const c = 1024
|
|
const d = b || 2
|
|
const e = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
|
const f = Math.floor(Math.log(a) / Math.log(c))
|
|
return parseFloat((a / Math.pow(c, f)).toFixed(d)) + ' ' + e[f]
|
|
}
|
|
|
|
const { hostname, port, protocol } = new URL(ipfsNodeUri)
|
|
|
|
const ipfsConfig: IpfsConfig = {
|
|
protocol: protocol.replace(':', ''),
|
|
host: hostname,
|
|
port: port || '443'
|
|
}
|
|
|
|
async function addToIpfs(
|
|
files: File[],
|
|
setFileSizeReceived: (size: string) => void,
|
|
ipfs: any
|
|
) {
|
|
const file = [...files][0]
|
|
const fileDetails = { path: file.name, content: file }
|
|
|
|
const response = await ipfs.add(fileDetails, {
|
|
wrapWithDirectory: true,
|
|
progress: (length: number) => setFileSizeReceived(formatBytes(length, 0))
|
|
})
|
|
|
|
// CID of wrapping directory is returned last
|
|
const cid = `${response[response.length - 1].hash}/${file.name}`
|
|
return cid
|
|
}
|
|
|
|
export default function Add() {
|
|
const { ipfs, isIpfsReady, ipfsError } = useIpfsApi(ipfsConfig)
|
|
const [fileHash, setFileHash] = useState()
|
|
const [loading, setLoading] = useState(false)
|
|
const [message, setMessage] = useState()
|
|
const [error, setError] = useState()
|
|
const [fileSize, setFileSize] = useState()
|
|
const [fileSizeReceived, setFileSizeReceived] = useState('')
|
|
|
|
useEffect(() => {
|
|
setMessage(
|
|
`Adding to IPFS<br />
|
|
<small>${fileSizeReceived || 0}/${fileSize}</small><br />`
|
|
)
|
|
}, [fileSize, fileSizeReceived])
|
|
|
|
async function handleOnDrop(acceptedFiles: File[]) {
|
|
if (!acceptedFiles[0]) return
|
|
|
|
setLoading(true)
|
|
setError(null)
|
|
|
|
const totalSize = formatBytes(acceptedFiles[0].size, 0)
|
|
setFileSize(totalSize)
|
|
|
|
try {
|
|
const cid = await addToIpfs(acceptedFiles, setFileSizeReceived, ipfs)
|
|
if (!cid) return
|
|
setFileHash(cid)
|
|
setLoading(false)
|
|
} catch (error) {
|
|
setError(`Adding to IPFS failed: ${error.message}`)
|
|
return null
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className={styles.add}>
|
|
{loading ? (
|
|
<Spinner message={message} />
|
|
) : fileHash ? (
|
|
<a
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
href={`${ipfsGateway}/ipfs/${fileHash}`}
|
|
>
|
|
ipfs://{fileHash}
|
|
</a>
|
|
) : (
|
|
<Dropzone
|
|
multiple={false}
|
|
handleOnDrop={handleOnDrop}
|
|
disabled={!isIpfsReady}
|
|
error={error || ipfsError}
|
|
/>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|