Skip to content

Commit

Permalink
MUI@5.8.1 (#61)
Browse files Browse the repository at this point in the history
  • Loading branch information
boonya authored May 30, 2022
1 parent 7b3be28 commit 79deb1e
Show file tree
Hide file tree
Showing 13 changed files with 633 additions and 82 deletions.
3 changes: 3 additions & 0 deletions client/main.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
name="viewport"
content="width=device-width, height=device-height, viewport-fit=cover, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
/>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fira+Sans+Extra+Condensed&display=swap" rel="stylesheet">
<meta name="mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
</head>
Expand Down
18 changes: 13 additions & 5 deletions imports/ui/App.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import Discover from './Discover';
import List from './List';
import RootLayout from './RootLayout';
import createTheme from './theme';
import CssBaseline from '@mui/material/CssBaseline';
import Typography from '@mui/material/Typography';
import {ThemeProvider} from '@mui/material/styles';
import React from 'react';

export function App() {
return (
<div>
<h1>IP Web Cams Recorder</h1>
<List />
<Discover />
</div>
<ThemeProvider theme={createTheme()}>
<CssBaseline />
<RootLayout>
<Typography variant="h1">IP Web Cams Recorder</Typography>
<List />
<Discover />
</RootLayout>
</ThemeProvider>
);
}
20 changes: 11 additions & 9 deletions imports/ui/Discover/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import Collection from '../../api/camera';
import {callMethod} from '../../api/methods';
import METHODS from '../../methods';
import Content from './Content';
import Button from '@mui/material/Button';
import Checkbox from '@mui/material/Checkbox';
import FormControlLabel from '@mui/material/FormControlLabel';
import Grid from '@mui/material/Grid';
import {useTracker} from 'meteor/react-meteor-data';
import React from 'react';

Expand Down Expand Up @@ -41,14 +45,12 @@ export default function Discover() {
}, [discovered, filter, added]);

return (
<div>
<button type="button" onClick={handleDiscover} disabled={processing}>Discover new camera</button>
<label>
Show added <input type="checkbox" onClick={handleFilter} />
</label>
<div>
<Content pending={pending} processing={processing} error={error} list={list} added={added} />
</div>
</div>
<Grid container direction="column" rowGap={3}>
<Grid item>
<Button onClick={handleDiscover} disabled={processing}>Discover new camera</Button>
</Grid>
<FormControlLabel control={<Checkbox onClick={handleFilter} />} label="Show added" />
<Content pending={pending} processing={processing} error={error} list={list} added={added} />
</Grid>
);
}
38 changes: 17 additions & 21 deletions imports/ui/List/Item.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@ import {callMethod} from '../../api/methods';
import {CAMERA_STATE} from '../../constants';
import METHODS from '../../methods';
import {logError} from '../../utils/logger';
import RecordButton from './RecordButton';
import DeleteIcon from '@mui/icons-material/Delete';
import IconButton from '@mui/material/IconButton';
import ListItem from '@mui/material/ListItem';
import ListItemText from '@mui/material/ListItemText';
import Tooltip from '@mui/material/Tooltip';
import PropTypes from 'prop-types';
import React from 'react';
import React, {useCallback} from 'react';

export default function Item({_id, title, state}) {
const handleToggle = React.useCallback(async () => {
try {
await callMethod(METHODS.CAMERA_TOGGLE, _id);
}
catch (err) {
logError('Failed to toggle state of camera.')(err);
}
}, [_id]);

const handleRemove = React.useCallback(async () => {
const handleRemove = useCallback(async () => {
// eslint-disable-next-line no-alert
if (confirm('Do you really want to remove a camera?')) {
try {
Expand All @@ -27,17 +24,16 @@ export default function Item({_id, title, state}) {
}
}, [_id]);

const toggleButtonLabel = React.useMemo(() => {
return state === CAMERA_STATE.rec ? 'Stop recording' : 'Start recording';
}, [state]);

return (
<div>
{title}{' / '}
{state || CAMERA_STATE.idle}{' / '}
<button type="button" onClick={handleToggle}>{toggleButtonLabel}</button>{' / '}
<button type="button" onClick={handleRemove}>Remove</button>
</div>
<ListItem>
<ListItemText primary={title} secondary={state || CAMERA_STATE.idle} />
<RecordButton _id={_id} state={state} />
<Tooltip title="Remove">
<IconButton onClick={handleRemove} aria-label="Remove">
<DeleteIcon />
</IconButton>
</Tooltip>
</ListItem>
);
}

Expand Down
55 changes: 55 additions & 0 deletions imports/ui/List/RecordButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {callMethod} from '../../api/methods';
import {CAMERA_STATE} from '../../constants';
import METHODS from '../../methods';
import {logError} from '../../utils/logger';
import RecordIcon from '@mui/icons-material/FiberManualRecord';
import StopIcon from '@mui/icons-material/Stop';
import IconButton from '@mui/material/IconButton';
import Tooltip from '@mui/material/Tooltip';
import PropTypes from 'prop-types';
import React, {useMemo, useCallback, useState, useRef, useEffect} from 'react';

export default function RecordButton({_id, state}) {
const [loading, setLoading] = useState(false);
const prevState = useRef(state);

const label = useMemo(() => {
return state === CAMERA_STATE.rec ? 'Stop recording' : 'Start recording';
}, [state]);

const StateIcon = useMemo(() => {
return state === CAMERA_STATE.rec ? StopIcon : RecordIcon;
}, [state]);

const onClick = useCallback(async () => {
try {
setLoading(true);
await callMethod(METHODS.CAMERA_TOGGLE, _id);
}
catch (err) {
logError('Failed to toggle state of camera.')(err);
}
}, [_id]);

useEffect(() => {
if (prevState.current !== state) {
setLoading(false);
prevState.current = state;
}
}, [state]);

return (
<Tooltip title={label}>
<span>
<IconButton onClick={onClick} aria-label={label} disabled={loading}>
<StateIcon />
</IconButton>
</span>
</Tooltip>
);
}

RecordButton.propTypes = {
_id: PropTypes.string.isRequired,
state: PropTypes.string.isRequired,
};
7 changes: 4 additions & 3 deletions imports/ui/List/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import Collection from '../../api/camera';
import Item from './Item';
import MuiList from '@mui/material/List';
import {useTracker} from 'meteor/react-meteor-data';
import React from 'react';

export default function List() {
const list = useTracker(() => Collection.find().fetch());

return (
<ul>
{list.map((cam) => <li key={cam._id}><Item {...cam} /></li>)}
</ul>
<MuiList>
{list.map((cam) => <Item key={cam._id} {...cam} />)}
</MuiList>
);
}
27 changes: 27 additions & 0 deletions imports/ui/RootLayout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import styled from '@emotion/styled';
import Grid from '@mui/material/Grid';
import PropTypes from 'prop-types';
import React from 'react';

const Container = styled(Grid)`
padding: ${({theme}) => theme.spacing(3)};
height: 100%;
`;

export default function RootLayout({children, ...props}) {
return (
<Container
container
direction="column"
rowGap={3}
component="main"
{...props}
>
{children}
</Container>
);
}

RootLayout.propTypes = {
children: PropTypes.node.isRequired,
};
27 changes: 27 additions & 0 deletions imports/ui/theme/components.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export default () => ({
MuiCssBaseline: {
styleOverrides: {
'html, body, #root': {
padding: 0,
margin: 0,
height: '100%',
},
},
},
MuiButton: {
defaultProps: {
variant: 'contained',
},
},
MuiIconButton: {
defaultProps: {
color: 'primary',
},
},
MuiTextField: {
defaultProps: {
fullWidth: true,
margin: 'none',
},
},
});
10 changes: 10 additions & 0 deletions imports/ui/theme/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import createComponents from './components';
import createPalette from './palette';
import createTypography from './typography';
import {createTheme} from '@mui/material';

export default (...args) => createTheme({
palette: createPalette(...args),
typography: createTypography(...args),
components: createComponents(...args),
});
17 changes: 17 additions & 0 deletions imports/ui/theme/palette.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export default () => ({
mode: 'dark',
primary: {
main: '#7cb342',
},
secondary: {
main: '#ff6e40',
},
text: {
primary: '#aab4be',
secondary: '#fdfeff',
},
background: {
default: '#072111',
paper: '#0d290a',
},
});
29 changes: 29 additions & 0 deletions imports/ui/theme/typography.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export default () => ({
fontFamily: "'Fira Sans Extra Condensed', sans-serif",
htmlFontSize: 16,
fontSize: 16,
h1: {
fontSize: '3rem',
fontWeight: 'bold',
},
h2: {
fontSize: '2rem',
fontWeight: 'bold',
},
h3: {
fontSize: '1.5rem',
fontWeight: 'bold',
},
h4: {
fontSize: '1.25rem',
fontWeight: 'bold',
},
h5: {
fontSize: '1.1rem',
fontWeight: 'bold',
},
h6: {
fontSize: '1rem',
fontWeight: 'bold',
},
});
Loading

0 comments on commit 79deb1e

Please sign in to comment.