/- *boke /+ kaji, sr=sortug, lib=boke /= post-text /web/components/post-text |_ [s=state =bowl:gall] ++ css ^~ %- trip ''' #tv{ padding: 1rem; & main{ margin-top: 0.5rem; height: 50vw; & #screen{ } & #chat{ border: 1px solid var(--text-color); h3{ height: 1.5rem; margin: 0; } & #chat-container{ overflow-y: scroll; max-height: calc(100% - 3.5rem); height: calc(100% - 3.5rem); .chat-msg{ padding: 0.5rem; & .author{ opacity: 0.8; font-family: Inter; } & .chat-content{ padding: 0.3rem 1rem; & p{ margin: 0; } } } } & form{ display: flex; margin-bottom: 0; border-top: 1px solid black; & input{ border: none; border-radius: 0; } & input[type=text]{ width: 100%; height: 2rem; } & input[type=submit]{ padding: 0.2rem; } } } } & #radio-list{ overflow-y: scroll; max-height: 70vh; & .entry{ cursor: pointer; } } } #video{ width: 100%; background-color: black; } .tabs{ display: flex; gap: 1rem; & .tab{ cursor: pointer; } } @media (min-width: 1200px){ #tv main{ display: flex; align-items: stretch; gap: 1rem; } #screen{ width: 75%; } #chat{ width: 25%; } @media (max-width: 1200px){ #screen{ width: 100%; } #chat{ width: 25%; } } .movie-name{ font-size: 1.2rem; font-weight: 500; } ''' ++ script |= sub-path=tape ^~ %+ weld %- trip ''' function initVideo(videoSrc){ const video = document.getElementById('video'); video.autoplay = true; console.log(videoSrc, "starting video") if (Hls.isSupported()) { var hls = new Hls(); hls.loadSource(videoSrc); hls.attachMedia(video); hls.on(Hls.Events.MANIFEST_LOADED, function (event, data) { console.log("manifest loaded", [event, data]) }); hls.on(Hls.Events.MANIFEST_LOADED, function (event, data) { console.log("manifest loaded", [event, data]) }); hls.on(Hls.Events.FRAG_LOADED, function (event, data) { console.log("frag loaded", [event, data]) }); hls.on(Hls.Events.LEVEL_LOADED, function (event, data) { console.log("level loaded", [event, data]) }); hls.on(Hls.Events.SUBTITLE_TRACK_SWITCH, function (event, data) { console.log("sub switch", [event, data]) }); hls.on(Hls.Events.SUBTITLE_TRACK_LOADED, function (event, data) { console.log("sub loaded", [event, data]) }); hls.on(Hls.Events.MANIFEST_PARSED, function (event, data) { console.log("manifest parsed", [event, data]) video.play(); }); } // HLS.js is not supported on platforms that natively support HLS else if (video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoSrc; video.addEventListener('loadedmetadata', function () { video.play(); }); } } document.addEventListener('DOMContentLoaded', () => { const src = 'https://hydrogen.finnem.net/hls/live.m3u8'; //const src = 'https://hls.urbit.cam/output.m3u8'; initVideo(src); const room = document.getElementById("chat-container"); if (room) room.scrollTop = room.scrollHeight }); document.addEventListener('kaji-fact', (event) => { console.log(event.detail, "kaji fact") if (event.detail.event === "scroll"){ const room = document.getElementById("chat-container"); if (room) setTimeout(() => room.scrollTop = room.scrollHeight, 50) } else if ("change-radio" in event.detail) initVideo(event.detail["change-radio"]); }); ''' """ subscribe('{sub-path}'); """ ++ main |= [symbol=@tas =twr] ^- manx =/ author (scow %p owner.twr) =/ name (trip symbol) =/ sub-path "/tv/{(trip -.twr)}/{name}" ~& sub-path=sub-path ;div#tv ;style: {css} ;main ;div#screen ;video#video =controls "" ; == ;+ (broadcast-metadata twr) == ;+ (chat-box symbol twr) == :: ;+ rl ;script: {(script sub-path)} ;script@"https://cdn.jsdelivr.net/npm/hls.js@latest"; == ++ broadcast-metadata |= =twr ^- manx =/ author (scow %p owner.twr) =/ stat-name (trip name.twr) ?: ?=(%our -.twr) =/ desc (trip description.tv.twr) ;div.meta ;div.movie-name:"{desc}" ;div.movie-from:"from {stat-name} by {author}" == :: =/ desc (trip description.p.twr) ;div.meta ;div:"{desc}" ;div:"by {author}" == ++ rl ^- manx ;div#radio-list ;div.tabs =kaji "scry" =swap "swap" =targ "#rlist" ;div.tab =path "/tv/f/s" ; Spandrell TV == ;div.tab =path "/tv/f/u" ; Urbit Radio == == ;div#rlist ;* tv-list == == ++ radio-list ^- marl %+ turn ~(tap by urbit.tv.s) |= [p=@p q=urbit-radio] ;div.entry =kaji "poke" =action "change-radio" =payload (enc:kaji p) ;p:"{(trip description.q)}" ;p:"by {(scow %p p)}" == ++ tv-list ^- marl %+ turn ~(tap by here.tv.s) |= [p=@t q=bstv] ;div.entry =kaji "poke" =action "change-nradio" =payload (trip p) ;p:"{(trip playing.current.q)}" ;p:"by {(scow %p owner.q)}" == ++ chat-box |= [symbol=@tas =twr] ?: ?=(%urb -.twr) ;div; ;div#chat ;h3.tc.bb:"Chat" ;div#chat-container ;* %+ turn (flop chat.tv.twr) chat-msg == ;form =id "chat-composer" =kaji "poke" =action "add-radio-chat" =wipe "yes" ;input#text-input(type "text", name "input", placeholder "Nice", autocomplete "off"); ;input(type "hidden", name "type", value (trip -.twr)); ;input(type "hidden", name "owner", value (scow %p owner.twr)); ;input(type "hidden", name "name", value (trip symbol)); ;input(type "submit", value "⇛"); == == ++ chat-msg |= p=post:tp :: =/ usr (user author.p whoms 32) =/ author ?: (is-anon:lib author.p) "anon" (scow %p author.p) ;div.chat-msg ;div.f1 ;div.author:"{author}:" ;div.time:"{(time-to-tape:string:sr id.p)}" == ;div.chat-content ;* (content:post-text contents.p) == == --