Add option to select which channels will be displayed on the playersite (#392, #800)

This commit is contained in:
Ingo Oppermann 2024-09-13 15:33:47 +02:00
parent 4a88f47af5
commit 9e81f203cb
No known key found for this signature in database
GPG Key ID: 2AB32426E9DD229E
3 changed files with 114 additions and 10 deletions

View File

@ -15,16 +15,9 @@ const MenuProps = {
export default function Component(props) {
return (
<FormControl variant="outlined" fullWidth>
<FormControl variant={props.variant} disabled={props.disabled} fullWidth>
<InputLabel>{props.label}</InputLabel>
<Select
multiple
value={props.value}
onChange={props.onChange}
input={<OutlinedInput />}
renderValue={(selected) => selected.join(', ')}
MenuProps={MenuProps}
>
<Select multiple value={props.value} onChange={props.onChange} input={<OutlinedInput />} renderValue={props.renderValue} MenuProps={MenuProps}>
{props.children}
</Select>
</FormControl>
@ -32,7 +25,10 @@ export default function Component(props) {
}
Component.defaultProps = {
variant: 'outlined',
label: '',
value: [],
disabled: false,
renderValue: (selected) => selected.join(', '),
onChange: function (event) {},
};

View File

@ -2247,6 +2247,7 @@ class Restreamer {
player: 'videojs',
playersite: false,
channelid: 'current',
channel_list: this.ListChannels().map((c) => c.channelid),
title: 'restreamer',
share: true,
support: true,
@ -2311,7 +2312,8 @@ class Restreamer {
channel = this.GetChannel(this.GetCurrentChannelID());
}
const channels = this.ListChannels();
// filter channels based on the main channel and additional channels
const channels = this.ListChannels().filter((c) => settings.channel_list.indexOf(c.channelid) !== -1 || c.channelid === channel.channelid);
// Handlebars function ifEquals
Handlebars.registerHelper('ifEquals', function (arg1, arg2, options) {

View File

@ -14,6 +14,11 @@ import Tab from '@mui/material/Tab';
import Tabs from '@mui/material/Tabs';
import TextField from '@mui/material/TextField';
import Typography from '@mui/material/Typography';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import * as M from '../utils/metadata';
import playerSiteThumb from '../assets/images/playersite.png';
@ -23,6 +28,8 @@ import Dialog from '../misc/modals/Dialog';
import Filesize from '../misc/Filesize';
import FormInlineButton from '../misc/FormInlineButton';
import H from '../utils/help';
import MultiSelect from '../misc/MultiSelect';
import MultiSelectOption from '../misc/MultiSelectOption';
import NotifyContext from '../contexts/Notify';
import Paper from '../misc/Paper';
import PaperHeader from '../misc/PaperHeader';
@ -49,6 +56,61 @@ const imageTypes = [
const templateTypes = [{ mimetype: 'text/html', extension: 'html', maxSize: 500 * 1024 }];
function CheckboxList(props) {
const [$checked, setChecked] = React.useState(props.selected);
const handleToggle = (value) => () => {
const currentIndex = $checked.indexOf(value);
const newChecked = [...$checked];
if (currentIndex === -1) {
newChecked.push(value);
} else {
newChecked.splice(currentIndex, 1);
}
setChecked(newChecked);
props.onChange({
target: {
value: [...newChecked],
},
});
};
return (
<List sx={{ width: '100%', position: 'relative', overflow: 'auto', maxHeight: 300 }}>
{props.items.map((value) => {
const labelId = `checkbox-list-label-${value.id}`;
return (
<ListItem key={value.id} disablePadding>
<ListItemButton onClick={handleToggle(value.id)} dense disabled={props.disabled}>
<ListItemIcon>
<Checkbox
edge="start"
checked={$checked.indexOf(value.id) !== -1}
tabIndex={-1}
disableRipple
inputProps={{ 'aria-labelledby': labelId }}
/>
</ListItemIcon>
<ListItemText id={labelId} primary={value.name} />
</ListItemButton>
</ListItem>
);
})}
</List>
);
}
CheckboxList.defaultProps = {
disabled: false,
selected: [],
items: [],
onChange: function () {},
};
export default function Playersite(props) {
const classes = useStyles();
const navigate = useNavigate();
@ -250,6 +312,12 @@ export default function Playersite(props) {
return null;
}
let main_channelid = props.restreamer.GetCurrentChannelID();
let channel = props.restreamer.GetChannel($settings.channelid);
if (channel !== null) {
main_channelid = channel.channelid;
}
return (
<React.Fragment>
<Paper xs={12} md={10}>
@ -322,6 +390,44 @@ export default function Playersite(props) {
<Trans>Main page channel (index.html).</Trans>
</Typography>
</Grid>
<Grid item xs={12}>
<MultiSelect
disabled={!$settings.playersite}
type="select"
label={<Trans>Additional channels</Trans>}
value={$settings.channel_list.filter((c) => c !== main_channelid)}
renderValue={(selected) => {
return selected
.map((id) => {
let channel = props.restreamer.GetChannel(id);
if (channel === null) {
return '';
}
return channel.name;
})
.filter((name) => name.length !== 0)
.join(', ');
}}
onChange={handleChange('channel_list')}
>
{$channels
.sort((a, b) => {
const aname = a.name.toUpperCase();
const bname = b.name.toUpperCase();
return aname < bname ? -1 : aname > bname ? 1 : 0;
})
.map((c) => {
return { id: c.channelid, name: c.name };
})
.filter((c) => c.id !== main_channelid)
.map((c) => {
return <MultiSelectOption key={c.id} value={c.id} name={c.name} />;
})}
</MultiSelect>
<Typography variant="caption">
<Trans>Additional channels to display on the playersite.</Trans>
</Typography>
</Grid>
<Grid item xs={12}>
<Checkbox
label={<Trans>Share button</Trans>}