This commit is contained in:
TreetopFlyer 2022-04-22 16:56:41 -04:00
commit 6825123206
3 changed files with 178 additions and 0 deletions

83
app.js Normal file
View File

@ -0,0 +1,83 @@
// @ts-check
/// <reference path="./types.d.ts"/>
import { h, html, render } from "https://esm.sh/htm/preact";
import { createContext, Fragment } from 'https://esm.sh/preact';
import { useReducer, useState, useEffect, useLayoutEffect, useMemo, useRef } from 'https://esm.sh/preact/hooks';
/** @type {(props:{channel:string, interval:number})=>any} */
const App = props =>
{
/** @type {Boxcast.StateBinding<Array<Boxcast.Broadcast>>} */
const [ListGet, ListSet] = useState([]);
/** @type {Boxcast.StateBinding<Boxcast.Broadcast>} */
const Selected = useState(false);
useEffect(()=>
{
Ping();
const timer = setInterval(Ping, props.interval);
return ()=>clearInterval(timer);
}
, []);
/** @type {()=>Promise} */
const Ping = async () =>
{
const response = await fetch(`https://rest.boxcast.com/channels/${props.channel}/broadcasts?s=starts_at&l=1000`);
const json = await response.json();
ListSet(json);
};
return html`
<div class="Playlist">
${
ListGet.map(item => html`<${BroadcastItem} item=${item} active=${Selected} />`)
}
</div>
`;
}
/** @type {(props:{item:Boxcast.Broadcast, active:Boxcast.StateBinding<Boxcast.Broadcast>})=>any} */
const BroadcastItem = ({item, active}) =>
{
const startDate = useMemo(()=>DateParse(item.starts_at), [item.starts_at]);
return html`
<div key=${item.id} onClick=${()=>active[1](item)}>
<span>${startDate.Month} ${startDate.Date}</span>
<strong>${item.name}</strong>
<span>${startDate.Hours}:${startDate.Minutes} ${startDate.M}</span>
${
active[0]?.id == item.id ? html`<dd>Active</dd>` : null
}
</div>
`;
};
/** @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(),
};
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;
};
export default App;

49
index.html Normal file
View File

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html>
<head></head>
<body>
<div id="boxcast-player"></div>
<div id="boxcast-playlist"></div>
<script type="module">
import 'https://js.boxcast.com/v3.min.js';
const Channel = {
Basics: "sfz7ja3rlpoous6usu8a",
Sunday: "gzahmhugrzogttfdtbjj",
Dev: "r3os2zfdnhlquhuypgtp"
};
/*
const Player = boxcast("#boxcast-player");
Player.loadChannel(Channels.Basics,
{
showTitle: true,
showDescription: true,
showCountdown: true,
//selectedBroadcastId: "yo8sefnnejvw3cx3vhup",
//showRelated: true,
//relatedBroadcastsQuery: {q: "timeframe:relevant starts_at:[2022-01-01 TO 2022-12-01]"},
onLoadBroadcast: console.log,
autoplay: true,
defaultVideo: "next"
});
*/
import { h, html, render } from "https://esm.sh/htm/preact";
import App from "./app.js";
render(
h(App, {channel:Channel.Basics, interval:5000}),
document.querySelector("#boxcast-playlist")
);
</script>
</body>
</html>

46
types.d.ts vendored Normal file
View File

@ -0,0 +1,46 @@
namespace Boxcast
{
type Broadcast =
{
account_id:string
channel_id:string
description:string
id:string
name:string
poster:string
preview:string
starts_at:string
stops_at:string
tags:Array<string>
timeframe: "future" | "preroll" | "current" | "past"
start?: Date
stop?: Date
}
type Date =
{
Zone: string | RegExpMatchArray
Day: "Sunday" | "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | string
Month: "January" | "February" | "March" | "April" | "May" | "June" | "July" | "August" | "September" | "October" | "November" | "December" | string
Date: number
Hours: number
Minutes: string | number
M?: "AM" | "PM"
}
type StateBinding<T> = [T, (item:T)=>void];
}
namespace Store
{
type State =
{
Channel:string,
List:Array<Boxcast.Broadcast>,
Active:false | Boxcast.Broadcast
}
type Action = ["ping-out"] | ["ping-back", Array<Boxcast.Broadcast>] | ["select", Boxcast.Broadcast]
type Reducer = (inState:State, inAction:Action) => inState
}