MUI update

This commit is contained in:
2022-05-06 00:49:23 +02:00
parent 053bb884d4
commit 018b208835
18 changed files with 1726 additions and 680 deletions

194
frontend/src/Home.tsx Normal file
View File

@@ -0,0 +1,194 @@
import { Backdrop, Button, CircularProgress, Container, Grid, Paper, Snackbar, TextField, } from "@mui/material";
import React, { Fragment, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Socket } from "socket.io-client";
import { StackableResult } from "./components/StackableResult";
import { connected, disconnected, downloading, finished } from "./features/status/statusSlice";
import { IDLInfo, IDLInfoBase, IMessage } from "./interfaces";
import { RootState } from "./stores/store";
import { updateInStateMap, } from "./utils";
type Props = {
socket: Socket
}
export default function Home({ socket }: Props) {
// redux state
const settings = useSelector((state: RootState) => state.settings)
const status = useSelector((state: RootState) => state.status)
const dispatch = useDispatch()
// ephemeral state
const [progressMap, setProgressMap] = useState(new Map<number, number>());
const [messageMap, setMessageMap] = useState(new Map<number, IMessage>());
const [downloadInfoMap, setDownloadInfoMap] = useState(new Map<number, IDLInfoBase>());
const [url, setUrl] = useState('');
const [showBackdrop, setShowBackdrop] = useState(false);
/* -------------------- Effects -------------------- */
/* WebSocket connect event handler*/
useEffect(() => {
socket.on('connect', () => {
dispatch(connected());
socket.emit('fetch-jobs')
socket.emit('disk-space')
socket.emit('retrieve-jobs');
})
return () => {
socket.disconnect()
}
}, [])
/* Ask server for pending jobs / background jobs */
useEffect(() => {
socket.on('pending-jobs', (count: number) => {
count === 0 ? setShowBackdrop(false) : setShowBackdrop(true)
})
}, [])
/* Handle download information sent by server */
useEffect(() => {
socket.on('info', (data: IDLInfo) => {
setShowBackdrop(false)
dispatch(downloading())
updateInStateMap(data.pid, data.info, downloadInfoMap, setDownloadInfoMap);
})
}, [])
/* Handle per-download progress */
useEffect(() => {
socket.on('progress', (data: IMessage) => {
if (showBackdrop) {
setShowBackdrop(false)
}
if (!status.downloading) {
dispatch(downloading())
}
if (data.status === 'Done!' || data.status === 'Aborted') {
updateInStateMap(data.pid, 'Done!', messageMap, setMessageMap);
updateInStateMap(data.pid, 0, progressMap, setProgressMap);
socket.emit('disk-space')
dispatch(finished())
return;
}
updateInStateMap(data.pid, data, messageMap, setMessageMap);
if (data.progress) {
updateInStateMap(data.pid, Math.ceil(Number(data.progress.replace('%', ''))), progressMap, setProgressMap)
}
})
}, [])
/* -------------------- component functions -------------------- */
/**
* Retrive url from input, cli-arguments from checkboxes and emits via WebSocket
*/
const sendUrl = () => {
socket.emit('send-url', {
url: url,
params: settings.cliArgs.toString(),
})
setUrl('')
setTimeout(() => {
const input = document.getElementById('urlInput') as HTMLInputElement;
input.value = '';
setShowBackdrop(true)
}, 250);
}
/**
* Update the url state whenever the input value changes
* @param e Input change event
*/
const handleUrlChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setUrl(e.target.value)
}
/**
* Abort a specific download if id's provided, other wise abort all running ones.
* @param id The download id / pid
* @returns void
*/
const abort = (id?: number) => {
if (id) {
updateInStateMap(id, null, downloadInfoMap, setDownloadInfoMap, true)
socket.emit('abort', { pid: id })
return
}
socket.emit('abort-all')
}
return (
<Container maxWidth="lg" sx={{ mt: 4, mb: 4 }}>
<Backdrop
sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }}
open={showBackdrop}
>
<CircularProgress color="primary" />
</Backdrop>
<Grid container spacing={2}>
<Grid item xs={12}>
<Paper
sx={{
p: 2,
display: 'flex',
flexDirection: 'column',
}}
>
<TextField
id="urlInput"
label={settings.i18n.t('urlInput')}
variant="outlined"
onChange={handleUrlChange}
/>
<Grid container spacing={1} pt={2}>
<Grid item>
<Button variant="contained" onClick={() => sendUrl()} disabled={false}>{settings.i18n.t('startButton')}</Button>
</Grid>
<Grid item>
<Button variant="contained" onClick={() => abort()}>{settings.i18n.t('abortAllButton')}</Button>
</Grid>
</Grid>
</Paper>
</Grid>
</Grid>
<Grid container spacing={{ xs: 2, md: 2 }} columns={{ xs: 4, sm: 8, md: 12 }} pt={2}>
{ /*Super big brain flatMap moment*/
Array
.from(messageMap)
.filter(flattened => [...flattened][0])
.filter(flattened => [...flattened][1].toString() !== 'Done!')
.flatMap(message => (
<Grid item xs={4} sm={8} md={6} key={message[0]}>
{
/*
Message[0] => key, the pid which is shared with the progress and download Maps
Message[1] => value, the actual formatted message sent from server
*/
}
<Fragment>
<StackableResult
formattedLog={message[1]}
title={downloadInfoMap.get(message[0])?.title}
thumbnail={downloadInfoMap.get(message[0])?.thumbnail}
resolution={downloadInfoMap.get(message[0])?.resolution}
progress={progressMap.get(message[0])}
stopCallback={() => abort(message[0])}
/>
</Fragment>
</Grid>
))
}
</Grid>
<Snackbar
open={status.connected}
autoHideDuration={1500}
message="Connected"
onClose={() => dispatch(disconnected())}
/>
</Container>
);
}