aboutsummaryrefslogtreecommitdiff
path: root/src/main/DeviceList.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/DeviceList.jsx')
-rw-r--r--src/main/DeviceList.jsx66
1 files changed, 66 insertions, 0 deletions
diff --git a/src/main/DeviceList.jsx b/src/main/DeviceList.jsx
new file mode 100644
index 00000000..eb51232f
--- /dev/null
+++ b/src/main/DeviceList.jsx
@@ -0,0 +1,66 @@
+import React, { useEffect, useRef, useState } from 'react';
+import { useDispatch } from 'react-redux';
+import makeStyles from '@mui/styles/makeStyles';
+import { FixedSizeList } from 'react-window';
+import AutoSizer from 'react-virtualized-auto-sizer';
+import { devicesActions } from '../store';
+import { useEffectAsync } from '../reactHelper';
+import DeviceRow from './DeviceRow';
+
+const useStyles = makeStyles((theme) => ({
+ list: {
+ maxHeight: '100%',
+ },
+ listInner: {
+ position: 'relative',
+ margin: theme.spacing(1.5, 0),
+ },
+}));
+
+const DeviceList = ({ devices }) => {
+ const classes = useStyles();
+ const dispatch = useDispatch();
+ const listInnerEl = useRef(null);
+
+ if (listInnerEl.current) {
+ listInnerEl.current.className = classes.listInner;
+ }
+
+ const [, setTime] = useState(Date.now());
+
+ useEffect(() => {
+ const interval = setInterval(() => setTime(Date.now()), 60000);
+ return () => {
+ clearInterval(interval);
+ };
+ }, []);
+
+ useEffectAsync(async () => {
+ const response = await fetch('/api/devices');
+ if (response.ok) {
+ dispatch(devicesActions.refresh(await response.json()));
+ } else {
+ throw Error(await response.text());
+ }
+ }, []);
+
+ return (
+ <AutoSizer className={classes.list}>
+ {({ height, width }) => (
+ <FixedSizeList
+ width={width}
+ height={height}
+ itemCount={devices.length}
+ itemData={devices}
+ itemSize={72}
+ overscanCount={10}
+ innerRef={listInnerEl}
+ >
+ {DeviceRow}
+ </FixedSizeList>
+ )}
+ </AutoSizer>
+ );
+};
+
+export default DeviceList;