diff --git a/CHANGELOG.md b/CHANGELOG.md index d5b82ef..9a88700 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## v1.8.0 > vx.x.x +- Add enlarged channel overview - Add new publication services: Rumble, PicartoTV, NimoTV, Livepush - Add frame interpolation (framerate) filter (thanks to orryverducci) - Add -referer option for pulling HTTP streams ([PR 40](https://github.com/datarhei/restreamer-ui/pull/40), thanks to mdastgheib) @@ -18,7 +19,7 @@ ## v1.7.0 > v1.8.0 -- Add Add stream key field and protocol detection to RTMP publication service +- Add stream key field and protocol detection to RTMP publication service - Add Chinese (simplified) translation (thanks to Huyg0180110559) - Add Ukrainian translation (thanks to Yurii Denys) - Fix empty force_key_frames value diff --git a/src/misc/ChannelList.js b/src/misc/ChannelList.js index 7f65b2b..e1df526 100644 --- a/src/misc/ChannelList.js +++ b/src/misc/ChannelList.js @@ -10,6 +10,8 @@ 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 FullscreenIcon from '@mui/icons-material/Fullscreen'; +import FullscreenExitIcon from '@mui/icons-material/FullscreenExit'; import Grid from '@mui/material/Grid'; import IconButton from '@mui/material/IconButton'; import LensIcon from '@mui/icons-material/Lens'; @@ -119,7 +121,7 @@ const ImageBackdrop = styled('span')(({ theme }) => ({ border: `2px solid ${theme.palette.primary.dark}`, })); -function ChannelButton(props) { +function ChannelButton(props, largeChannelList) { const classes = useStyles(); const theme = useTheme(); @@ -154,7 +156,7 @@ function ChannelButton(props) { } return ( - + {}, }; +const calculateColumnsPerRow = (breakpointSmall, breakpointMedium, breakpointLarge) => { + if (breakpointLarge) { + return 4; + } else if (breakpointMedium) { + return 3; + } else if (breakpointSmall) { + return 2; + } + return 1; +}; + +const calculateRowsToFit = (windowHeight, thumbnailHeight, otherUIHeight) => { + return Math.floor((windowHeight - otherUIHeight) / thumbnailHeight); +}; + export default function ChannelList(props) { const classes = useStyles(); const theme = useTheme(); @@ -205,8 +222,12 @@ export default function ChannelList(props) { open: false, name: '', }); + const [windowWidth, setWindowWidth] = React.useState(window.innerWidth); + const [windowHeight, setWindowHeight] = React.useState(window.innerHeight); - const { channels: allChannels, channelid, onClick, onState } = props; + const { channels: allChannels, channelid, onClick, onClose, onState } = props; + + const [$largeChannelList, setLargeChannelList] = React.useState(false); React.useEffect(() => { (async () => { @@ -246,19 +267,40 @@ export default function ChannelList(props) { disabled={channelid === channel.channelid} onClick={() => { onClick(channel.channelid); + if ($largeChannelList) { + onClose(); + } }} + largeChannelList={$largeChannelList} /> ); }); setChannels(channels); })(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [$pos, allChannels, $nChannels, channelid, onClick, onState]); const onMount = async () => { setPos(0); }; + React.useEffect(() => { + const handleResize = () => { + setWindowWidth(window.innerWidth); + setWindowHeight(window.innerHeight); + }; + + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, []); + + React.useEffect(() => { + const columns = calculateColumnsPerRow(breakpointSmall, breakpointMedium, breakpointLarge); + const rows = $largeChannelList ? calculateRowsToFit(windowHeight, 200, 60) : 1; + setNChannels(rows * columns); + }, [breakpointSmall, breakpointMedium, breakpointLarge, windowHeight, windowWidth, $largeChannelList]); + const handleAddChannelDialog = () => { setAddChannel({ ...$addChannel, @@ -282,6 +324,11 @@ export default function ChannelList(props) { return null; } + const handleLargeChannelList = () => { + setLargeChannelList(!$largeChannelList); + setPos(0); + }; + return ( {}} onClose={props.onClose} - sx={{ marginButtom: 60 }} + sx={{ + marginButtom: 60, + '& .MuiDrawer-paper': { + top: $largeChannelList ? '0px!important' : 'auto!important', + height: $largeChannelList ? '100vh' : 'auto', + }, + }} BackdropProps={{ invisible: true }} classes={{ paper: classes.drawerPaper, @@ -307,6 +360,9 @@ export default function ChannelList(props) { + + {$largeChannelList ? : } + @@ -327,7 +383,7 @@ export default function ChannelList(props) { - + {$channels}