From 9e81f203cb0fa1a0b0ad3dd96082b0f1d75a8e54 Mon Sep 17 00:00:00 2001 From: Ingo Oppermann Date: Fri, 13 Sep 2024 15:33:47 +0200 Subject: [PATCH] Add option to select which channels will be displayed on the playersite (#392, #800) --- src/misc/MultiSelect.js | 14 ++---- src/utils/restreamer.js | 4 +- src/views/Playersite.js | 106 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 10 deletions(-) diff --git a/src/misc/MultiSelect.js b/src/misc/MultiSelect.js index 821d6e6..6375eb6 100644 --- a/src/misc/MultiSelect.js +++ b/src/misc/MultiSelect.js @@ -15,16 +15,9 @@ const MenuProps = { export default function Component(props) { return ( - + {props.label} - } renderValue={props.renderValue} MenuProps={MenuProps}> {props.children} @@ -32,7 +25,10 @@ export default function Component(props) { } Component.defaultProps = { + variant: 'outlined', label: '', value: [], + disabled: false, + renderValue: (selected) => selected.join(', '), onChange: function (event) {}, }; diff --git a/src/utils/restreamer.js b/src/utils/restreamer.js index 2f0bc3d..5fcb4ef 100644 --- a/src/utils/restreamer.js +++ b/src/utils/restreamer.js @@ -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) { diff --git a/src/views/Playersite.js b/src/views/Playersite.js index b4c50a3..69e48b3 100644 --- a/src/views/Playersite.js +++ b/src/views/Playersite.js @@ -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 ( + + {props.items.map((value) => { + const labelId = `checkbox-list-label-${value.id}`; + + return ( + + + + + + + + + ); + })} + + ); +} + +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 ( @@ -322,6 +390,44 @@ export default function Playersite(props) { Main page channel (index.html). + + Additional channels} + 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 ; + })} + + + Additional channels to display on the playersite. + + Share button}