Add enlarged channel overview

This commit is contained in:
Jan Stabenow 2023-11-27 17:02:39 +01:00
parent f809eacabf
commit 6a24e68055
2 changed files with 63 additions and 6 deletions

View File

@ -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

View File

@ -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 (
<Grid item xs={12} sm={6} md={4} lg={3}>
<Grid item xs={12} sm={6} md={4} lg={3} style={{ paddingBottom: largeChannelList ? '10px' : 'auto' }}>
<ImageButton focusRipple disabled={props.disabled} onClick={props.onClick} style={{ width: props.width }}>
<Stack direction="column" spacing={0.5}>
<Image
@ -192,6 +194,21 @@ ChannelButton.defaultProps = {
onClick: () => {},
};
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 (
<React.Fragment>
<SwipeableDrawer
@ -289,7 +336,13 @@ export default function ChannelList(props) {
open={props.open}
onOpen={() => {}}
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) {
<IconButton color="inherit" size="large" onClick={handleAddChannelDialog}>
<AddIcon />
</IconButton>
<IconButton color="inherit" size="large" onClick={handleLargeChannelList}>
{$largeChannelList ? <FullscreenExitIcon /> : <FullscreenIcon />}
</IconButton>
<IconButton color="inherit" size="large" onClick={props.onClose}>
<CloseIcon />
</IconButton>
@ -327,7 +383,7 @@ export default function ChannelList(props) {
</IconButton>
</Stack>
<Stack direction="row" spacing={0} className={classes.channelItems}>
<Grid container spacing={0} justifyContent="center">
<Grid container spacing={0} justifyContent={$largeChannelList ? 'flex-start' : 'center'}>
{$channels}
</Grid>
</Stack>