// @ts-check /// import 'https://js.boxcast.com/v3.min.js'; import { h, html, render } from "https://esm.sh/htm/preact"; import { useReducer, useState, useEffect, useLayoutEffect, useMemo, useRef } from 'https://esm.sh/preact/hooks'; import State01 from "./testdata-01.json" assert { type: "json" }; import State02 from "./testdata-02.json" assert { type: "json" }; const Styles = { Broadcast: { position: "relative", display: "flex", padding: "5px 0 5px 0", }, Time: { width: "75px", marginRight: "5px", fontSize: "16px", textAlign: "right", }, Partition: { margin: "10px 0 0 0", }, Pointer: { width: "75px", }, Alert: { position: "fixed", right: "20px", bottom: "20px", width: "300px", height: "200px", background: "#333", borderRadius: "5px", transition: "all 0.4s", color: "#fff", } }; const PlayerID = "boxcast-player" /** @type {(props:{channel:string, interval:number})=>any} */ const App = props => { /** @type {Boxcast.StateBinding>} */ const [ListGet, ListSet] = useState([]); /** @type {Boxcast.StateBinding} */ const [SelectedGet, SelectedSet] = useState(null); /** @type {Boxcast.StateBinding} */ const [LiveGet, LiveSet] = useState(null); /** @type {(inList:Array)=>Array} */ const SortStart = (inList) => { inList.sort((a, b) => a.starts_at > b.starts_at ? 1 : -1); inList.forEach( item => item.start = DateParse(item.starts_at)); return inList; } const Player = useRef(null); // on mount useEffect(()=> { Player.current = boxcast(`#${PlayerID}`); /* Player.current.loadChannel(props.channel, { showTitle: true, showDescription: true, showCountdown: true, //selectedBroadcastId: "yo8sefnnejvw3cx3vhup", showRelated: false, onLoadBroadcast: console.log, autoplay: true, defaultVideo: "next" }); */ return; /** @type {()=>Promise} */ const Ping = async () => { const response = await fetch(`https://rest.boxcast.com/channels/${props.channel}/broadcasts?l=50`); /** @type {Array} */ const json = await response.json(); ListSet(SortStart(json)); }; Ping(); const timer = setInterval(Ping, props.interval); return ()=>clearInterval(timer); } , []); // on new list useEffect(()=> { let live; for(let i=0; i { // alert("New session is starting.") } , [LiveGet]); // on new video selected useEffect(()=> { Player.current.loadChannel(props.channel, { selectedBroadcastId: SelectedGet?.id, showTitle: true, showDescription: true, showCountdown: true, showRelated: false, autoplay: true, defaultVideo: "next" }); } , [SelectedGet]) return html`
${ ListGet.map( (item, index) => h( BroadcastItem, { item: item, previous: ListGet[index-1], priority: item.id == LiveGet?.id, selected: item.id == SelectedGet?.id, select: ()=>SelectedSet(item) } )) }
<${BroadcastAlert}>
`; } /** @type {(props:{item:Boxcast.Broadcast, previous: false | Boxcast.Broadcast, priority:boolean, selected:boolean, select:()=>void})=>any} */ const BroadcastItem = ({item, previous, priority, selected, select}) => { let pointerText; if(item.timeframe == "current" || item.timeframe == "preroll") { pointerText = `Live:`; } else if (priority) { pointerText = `Next:`; } let partition; if(!previous || (previous.start.Date !== item.start.Date)) { partition = html`

${item.start.Day}, ${item.start.Month} ${item.start.Date}

` } let buttonText; if(item.timeframe == "past") { buttonText = "Recording"; } if(item.timeframe == "current" || item.timeframe == "preroll") { buttonText = "Watch"; } if(item.timeframe == "future") { buttonText = "Preview"; } if(selected) { buttonText = "(Viewing)"; } return html` ${ partition }
${ pointerText }
${item.start.Hours}:${item.start.Minutes} ${item.start.M}
${item.name}
`; }; const BroadcastAlert = () => { return html`
X

A new session is starting.

`; } /** @type {(inDate:string)=>Boxcast.Date} */ const DateParse = (inDateString) => { let date = new Date(inDateString); /** @type {Boxcast.Date} */ let obj = { Zone: date.toString().match(/\(([A-Za-z\s].*)\)/), Day: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][date.getDay()], Month: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][date.getMonth()], Date: date.getDate(), Hours: date.getHours(), Minutes: date.getMinutes(), Epoch: date.valueOf() }; obj.Zone = obj.Zone ? obj.Zone[1] : "local time"; obj.M = obj.Hours >= 12 ? "PM" : "AM"; obj.Hours %= 12; if(obj.Hours == 0){ obj.Hours = 12; } if(obj.Minutes < 10){ obj.Minutes = "0"+obj.Minutes; } return obj; }; /** @type {(inChannel:string, inSelector:string)=>void} */ export default (inChannel, inSelector) => render(h(App, {channel:inChannel, interval:50000}), document.querySelector(inSelector));