import React from 'react'; import { Trans } from '@lingui/macro'; import { styled } from '@mui/material/styles'; import { useTheme } from '@mui/styles'; import makeStyles from '@mui/styles/makeStyles'; import useMediaQuery from '@mui/material/useMediaQuery'; import AddIcon from '@mui/icons-material/Add'; import Button from '@mui/material/Button'; import ButtonBase from '@mui/material/ButtonBase'; import CloseIcon from '@mui/icons-material/Close'; import DoNotDisturbAltIcon from '@mui/icons-material/DoNotDisturbAlt'; import Grid from '@mui/material/Grid'; import IconButton from '@mui/material/IconButton'; import LensIcon from '@mui/icons-material/Lens'; import NavigateBeforeIcon from '@mui/icons-material/NavigateBefore'; import NavigateNextIcon from '@mui/icons-material/NavigateNext'; import Stack from '@mui/material/Stack'; import SwipeableDrawer from '@mui/material/SwipeableDrawer'; import TextField from '@mui/material/TextField'; import Typography from '@mui/material/Typography'; import Dialog from './modals/Dialog'; const useStyles = makeStyles((theme) => ({ drawerPaper: { marginBottom: '60px', boxShadow: '0px -20px 10px -14px rgb(0 0 0 / 25%), 0px -20px 10px -10px rgb(0 0 0 / 10%)', paddingLeft: 50, paddingRight: 50, }, drawerButtons: { marginRight: '-15px!important', }, channel: { marginBottom: '1em', }, channelBar: { maxWidth: '1200px', }, channelItems: { width: '100%', maxWidth: '980px', }, iconButton: { '& .MuiSvgIcon-root': { fontSize: '2.5em', }, }, iconButtonLeft: { marginLeft: '-1.5em!important', paddingBottom: '1em', }, iconButtonRight: { marginRight: '-1.5em!important', paddingBottom: '1em', }, imageTitle: { textAlign: 'initial', padding: '.5em 0em 0em .1em', }, })); const ImageButton = styled(ButtonBase)(({ theme }) => ({ '&:hover, &.Mui-focusVisible': { zIndex: 1, '& .MuiImageBackdrop-root': { opacity: 0.2, }, }, '&:disabled': { '& .MuiImageBackdrop-root': { opacity: 0.2, }, '& .MuiTypography-root': { color: 'white', }, }, })); const Image = styled('span')(({ theme }) => ({ position: 'relative', })); const ImageSrc = styled('span')(({ theme }) => ({ position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, backgroundSize: 'cover', backgroundPosition: 'center 40%', borderRadius: 4, border: `2px solid ${theme.palette.primary.dark}`, })); const ImageAlt = styled('span')(({ theme }) => ({ position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', color: theme.palette.common.white, })); const ImageBackdrop = styled('span')(({ theme }) => ({ position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, backgroundColor: theme.palette.common.black, opacity: 0.5, transition: theme.transitions.create('opacity'), borderRadius: 4, border: `2px solid ${theme.palette.primary.dark}`, })); function ChannelButton(props) { const classes = useStyles(); const theme = useTheme(); let color = theme.palette.primary.main; switch (props.state) { case 'disconnected': color = theme.palette.primary.main; break; case 'connected': color = theme.palette.secondary.main; break; case 'disconnecting': case 'connecting': color = theme.palette.warning.main; break; case 'error': color = theme.palette.error.main; break; default: color = theme.palette.primary.main; break; } let color_active = theme.palette.primary.main; switch (props.disabled) { case true: color_active = theme.palette.primary.light; break; default: color_active = theme.palette.primary.dark; break; } return ( {props.title} ); } ChannelButton.defaultProps = { url: '', width: 200, title: '', state: '', disabled: false, onClick: () => {}, }; export default function ChannelList(props) { const classes = useStyles(); const theme = useTheme(); const breakpointSmall = useMediaQuery(theme.breakpoints.up('sm')); const breakpointMedium = useMediaQuery(theme.breakpoints.up('md')); const breakpointLarge = useMediaQuery(theme.breakpoints.up('lg')); const [$pos, setPos] = React.useState(-1); const [$nChannels, setNChannels] = React.useState(breakpointSmall ? (breakpointMedium ? (breakpointLarge ? 4 : 3) : 2) : 1); const [$channels, setChannels] = React.useState([]); const [$addChannel, setAddChannel] = React.useState({ open: false, name: '', }); const { channels: allChannels, channelid, onClick, onState } = props; React.useEffect(() => { (async () => { await onMount(); })(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); React.useEffect(() => { setNChannels(breakpointSmall ? (breakpointMedium ? (breakpointLarge ? 4 : 3) : 2) : 1); }, [breakpointSmall, breakpointMedium, breakpointLarge]); React.useEffect(() => { (async () => { if (allChannels.length === 0) { return; } let channels = allChannels .sort((a, b) => { const aname = a.name.toUpperCase(); const bname = b.name.toUpperCase(); return aname < bname ? -1 : aname > bname ? 1 : 0; }) .slice($pos, $pos + $nChannels); const states = await onState(channels.map((channel) => channel.id)); channels = channels.map((channel) => { return ( { onClick(channel.channelid); }} /> ); }); setChannels(channels); })(); }, [$pos, allChannels, $nChannels, channelid, onClick, onState]); const onMount = async () => { setPos(0); }; const handleAddChannelDialog = () => { setAddChannel({ ...$addChannel, open: !$addChannel.open, name: '', }); }; const handleAddChannelChange = (event) => { setAddChannel({ ...$addChannel, name: event.target.value, }); }; if (props.open === false) { return null; } if ($pos < 0) { return null; } return ( {}} onClose={props.onClose} sx={{ marginButtom: 60 }} BackdropProps={{ invisible: true }} classes={{ paper: classes.drawerPaper, }} disableScrollLock > Channels { setPos($pos - 1); }} disabled={$pos === 0} className={classes.iconButton} > {$channels} { setPos($pos + 1); }} disabled={$pos + $nChannels >= allChannels.length} className={classes.iconButton} > Add new channel} buttonsLeft={ } buttonsRight={ } > Enter a name for the new channel. Name} value={$addChannel.name} onChange={handleAddChannelChange} /> ); } ChannelList.defaultProps = { open: false, channelid: '', channels: [], onClose: () => {}, onClick: (channelid) => {}, onAdd: (name) => {}, onState: (channelids) => { const states = {}; for (let channelid of channelids) { states[channelid] = ''; } return states; }, };