diff options
-rw-r--r-- | src/containers/PollCreation/PollCreation.tsx | 46 | ||||
-rw-r--r-- | src/hooks/useS3Preupload.tsx | 48 |
2 files changed, 68 insertions, 26 deletions
diff --git a/src/containers/PollCreation/PollCreation.tsx b/src/containers/PollCreation/PollCreation.tsx index 64ab7fd..e613afd 100644 --- a/src/containers/PollCreation/PollCreation.tsx +++ b/src/containers/PollCreation/PollCreation.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React from 'react'; import { useHistory } from 'react-router-dom'; import { makeStyles } from '@material-ui/core/styles'; import { @@ -8,13 +8,14 @@ import { Container } from '@material-ui/core'; import { useSnackbar } from 'notistack'; -import axios from 'axios'; import PollCreationImage from './PollCreationImage'; import UserStrip from '../../components/UserStrip/UserStrip'; -import { get, post } from '../../requests'; +import { post } from '../../requests'; import { useAuth } from '../../hooks/useAuth'; import { useFeed } from '../../hooks/APIClient'; +import useS3Preupload from '../../hooks/useS3Preupload'; + const useStyles = makeStyles(theme => ({ root: { @@ -26,36 +27,29 @@ const useStyles = makeStyles(theme => ({ } })); + const PollCreation: React.FC = () => { const classes = useStyles(); const history = useHistory(); - const [left, setLeft] = useState<File | string>(); - const [right, setRight] = useState<File | string>(); const { enqueueSnackbar } = useSnackbar(); const { user } = useAuth(); const { mutate: updateFeed } = useFeed(); - - const readyToSubmit = left && right; - - const uploadFile = (file: File): Promise<string> => { - const headers = { 'Content-Type': 'image/png' }; - return get('/files') - .then(response => response.data) - .then(uploadUrl => axios.put(uploadUrl, file, { headers })) - .then(response => { - const { config: { url } } = response; - return url?.slice(0, url?.indexOf('?')) || ''; - }); - }; - - const resolveFile = async (file?: File | string): Promise<string> => { - if (file instanceof File) return uploadFile(file); - return file || ''; - }; + const { + setValue: setLeft, + progress: progressLeft, + resolve: resolveLeft, + isReady: isLeftReady + } = useS3Preupload(); + const { + setValue: setRight, + progress: progressRight, + resolve: resolveRight, + isReady: isRightReady + } = useS3Preupload(); const handleClick = async () => { - if (readyToSubmit) { - const [leftUrl, rightUrl] = await Promise.all([resolveFile(left), resolveFile(right)]); + if (isLeftReady && isRightReady) { + const [leftUrl, rightUrl] = await Promise.all([resolveLeft(), resolveRight()]); const contents = { left: { url: leftUrl }, @@ -84,7 +78,7 @@ const PollCreation: React.FC = () => { </div> <Button color="primary" - disabled={!readyToSubmit} + disabled={!(isLeftReady && isRightReady)} variant="contained" onClick={handleClick} fullWidth diff --git a/src/hooks/useS3Preupload.tsx b/src/hooks/useS3Preupload.tsx new file mode 100644 index 0000000..aeb1d65 --- /dev/null +++ b/src/hooks/useS3Preupload.tsx @@ -0,0 +1,48 @@ +import { useState, useCallback, useMemo } from 'react'; +import { get } from '../requests'; +import axios from 'axios'; + + +export default () => { + const [url, setUrl] = useState<string>(); + const [file, setFile] = useState<File>(); + const [progress, setProgress] = useState<number>(0); + + const isReady = useMemo(() => Boolean(file || url), [file, url]); + + + console.log({ file, url }) + + const setValue = useCallback((value: File | string | undefined): void => { + if (value instanceof File) { + setFile(value); + setUrl(undefined); + } else { + setUrl(value); + setFile(undefined); + } + }, [setUrl, setFile]); + + const handleUploadProgress = useCallback((progressEvent: any) => { + setProgress(Math.round((progressEvent.loaded * 100) / progressEvent.total)); + }, [setProgress]); + + const resolve = useCallback(async (): Promise<string> => { + if (file) { + const config = { + headers: { 'Content-Type': 'image/png' }, + onUploadProgress: handleUploadProgress + }; + + return get('/files') + .then(response => response.data) + .then(uploadUrl => axios.put(uploadUrl, file, config)) + .then(response => { + const { config: { url } } = response; + return url ? url.slice(0, url.indexOf('?')) : ''; + }); + } else return url || ''; + }, [file, handleUploadProgress, url]); + + return { setValue, isReady, resolve, progress }; +}; |