replaced ical library

This commit is contained in:
Benjamin Jones 2021-03-29 18:03:46 +02:00
parent f1bd7697fa
commit 5630705ea1
9 changed files with 101 additions and 63 deletions

View File

@ -3,6 +3,7 @@
"rules": { "rules": {
"indent": ["error", 2], "indent": ["error", 2],
"import/prefer-default-export": 0, "import/prefer-default-export": 0,
"react/require-default-props": 0 "react/require-default-props": 0,
"react/forbid-prop-types": 0
} }
} }

14
app.js
View File

@ -10,9 +10,8 @@ import { useEventStream } from './src/hooks/data'
import { useTimeout } from './src/hooks/timerHooks' import { useTimeout } from './src/hooks/timerHooks'
export default () => { export default () => {
const [isPlaying, setIsPlaying] = useState(false)
const [currentVideo, setCurrentVideo] = useState(null) const [currentVideo, setCurrentVideo] = useState(null)
const [streamIsLive, setStreamLive] = useState(false) const [streamIsLive, setStreamIsLive] = useState(false)
const [infoActive, setInfoActive] = useState(false) const [infoActive, setInfoActive] = useState(false)
const [minLoadTimePassed, setMinTimeUp] = useState(false) const [minLoadTimePassed, setMinTimeUp] = useState(false)
const { data, loading } = useEventStream() const { data, loading } = useEventStream()
@ -42,7 +41,7 @@ export default () => {
end: stream.end, end: stream.end,
}) })
) { ) {
setStreamLive(`${config.peertube_root}${stream.embedPath}`) setStreamIsLive(true)
} }
}) })
} }
@ -51,14 +50,7 @@ export default () => {
return ( return (
<div> <div>
{currentVideo && !infoActive && minLoadTimePassed ? ( {currentVideo && !infoActive && minLoadTimePassed ? (
<Video <Video video={currentVideo} setInfoActive={setInfoActive} />
playing={isPlaying}
setPlaying={setIsPlaying}
src={`${config.peertube_root}${currentVideo.embedPath}`}
title={currentVideo.title}
org={currentVideo.channel.displayName}
setInfoActive={setInfoActive}
/>
) : ( ) : (
<Info <Info
data={data} data={data}

View File

@ -18,6 +18,7 @@
"axios": "^0.21.1", "axios": "^0.21.1",
"date-fns": "^2.19.0", "date-fns": "^2.19.0",
"ical": "^0.8.0", "ical": "^0.8.0",
"ical.js": "^1.4.0",
"preact": "^10.5.12", "preact": "^10.5.12",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"styled-components": "^5.2.1" "styled-components": "^5.2.1"

View File

@ -24,6 +24,7 @@ export const ChatHeader = styled.div`
bottom: ${props => (props.chatIsOpen ? 'initial' : 0)}; bottom: ${props => (props.chatIsOpen ? 'initial' : 0)};
top: ${props => (props.chatIsOpen ? '4px' : 'initial')}; top: ${props => (props.chatIsOpen ? '4px' : 'initial')};
border-radius: ${ui.borderRadius}px 0 0 0; border-radius: ${ui.borderRadius}px 0 0 0;
z-index: 2;
height: 32px; height: 32px;
box-sizing: border-box; box-sizing: border-box;

View File

@ -1,14 +1,24 @@
import { h } from 'preact' import { h } from 'preact'
import { useEffect, useRef, useState } from 'preact/hooks' import { useEffect, useRef, useState } from 'preact/hooks'
import { bool, func, string } from 'prop-types' import {
bool,
func,
instanceOf,
number,
object,
shape,
string,
} from 'prop-types'
import 'regenerator-runtime/runtime' import 'regenerator-runtime/runtime'
import { PeerTubePlayer } from '@peertube/embed-api' import { PeerTubePlayer } from '@peertube/embed-api'
import Chat from '../Chat' import Chat from '../Chat'
import Overlay from '../VideoOverlay' import Overlay from '../VideoOverlay'
import { VideoWrapper, Iframe } from './styles' import { VideoWrapper, Iframe } from './styles'
import config from '../../data/config'
const Video = ({ playing, setPlaying, src, title, org, setInfoActive }) => { const Video = ({ video, org, setInfoActive }) => {
const [isPlaying, setPlaying] = useState(false)
const videoiFrame = useRef(null) const videoiFrame = useRef(null)
const overlayTimeout = useRef(null) const overlayTimeout = useRef(null)
const [videoReady, setVideoReady] = useState(false) const [videoReady, setVideoReady] = useState(false)
@ -27,14 +37,11 @@ const Video = ({ playing, setPlaying, src, title, org, setInfoActive }) => {
setVideo() setVideo()
}, []) }, [])
useEffect(() => { const playVideo = () => {
const { current: player } = ptVideo const { current: player } = ptVideo
if (!videoReady) return if (!videoReady) return
if (playing) { setPlaying(true)
setOverlayActiveState(false)
try { try {
player.play() player.play()
} catch (error) { } catch (error) {
@ -42,11 +49,28 @@ const Video = ({ playing, setPlaying, src, title, org, setInfoActive }) => {
setOverlayActiveState(true) setOverlayActiveState(true)
setPlaying(false) setPlaying(false)
} }
} else {
setOverlayActiveState(true)
player.pause()
} }
}, [playing]) const pauseVideo = () => {
const { current: player } = ptVideo
setPlaying(false)
setOverlayActiveState(true)
try {
player.pause()
} catch (error) {
console.log({ error })
setPlaying(true)
setOverlayActiveState(false)
}
}
const toggleVideo = () => {
console.log('clicked')
if (isPlaying) {
pauseVideo()
} else {
playVideo()
}
}
const toggleFullscreen = () => { const toggleFullscreen = () => {
if (!document.fullscreenElement) { if (!document.fullscreenElement) {
@ -58,15 +82,13 @@ const Video = ({ playing, setPlaying, src, title, org, setInfoActive }) => {
const handleKeyPress = keyCode => { const handleKeyPress = keyCode => {
if (keyCode === 32) { if (keyCode === 32) {
setPlaying(!playing) // key == 'space'
toggleVideo()
} }
if (keyCode === 70) { if (keyCode === 70) {
// key == 'f'
toggleFullscreen() toggleFullscreen()
} }
// if (keyCode === 70 && isFullscreen) {
// console.log('exitFullscreen')
// exitFullscreen()
// }
} }
useEffect(() => { useEffect(() => {
@ -90,22 +112,21 @@ const Video = ({ playing, setPlaying, src, title, org, setInfoActive }) => {
return ( return (
<VideoWrapper <VideoWrapper
$active={overlayActive || !playing} $active={overlayActive || !isPlaying}
onMouseMove={activateOverlay} onMouseMove={activateOverlay}
// ref={videoWrapperEl}
> >
<Overlay <Overlay
onClick={() => setPlaying(!playing)} onClick={toggleVideo}
active={overlayActive || !playing} active={overlayActive || !isPlaying}
title={title} title={video.title}
org={org}
setInfoActive={setInfoActive} setInfoActive={setInfoActive}
/> />
<Iframe <Iframe
sandbox="allow-same-origin allow-scripts allow-popups" sandbox="allow-same-origin allow-scripts allow-popups"
src={`${src}?api=1&controls=false`} src={`${config.peertube_root}${video.embedPath}?api=1&controls=false`}
frameborder="0" frameborder="0"
allowfullscreen allowfullscreen
allow="autoplay"
ref={videoiFrame} ref={videoiFrame}
/> />
<Chat /> <Chat />
@ -114,9 +135,23 @@ const Video = ({ playing, setPlaying, src, title, org, setInfoActive }) => {
} }
Video.propTypes = { Video.propTypes = {
playing: bool, video: shape({
setPlaying: func.isRequired, account: object,
src: string.isRequired, category: object,
channel: object,
description: string,
duration: number,
embedPath: string,
end: instanceOf(Date),
id: string,
language: object,
previewPath: string,
start: instanceOf(Date),
state: object,
title: 'Testing a livesteam :)',
videoUrl: string,
views: number,
}),
title: string.isRequired, title: string.isRequired,
org: string, org: string,
} }

View File

@ -9,15 +9,16 @@ export const VideoWrapper = styled.div`
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
/* pointer-events: none; */
cursor: ${props => (props.$active ? 'pointer' : 'none')}; cursor: ${props => (props.$active ? 'pointer' : 'none')};
` `
export const Iframe = styled.iframe` export const Iframe = styled.iframe`
z-index: -1;
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
pointer-events: none;
` `
export const Overlay = styled.div` export const Overlay = styled.div`
z-index: 2; z-index: 1;
position: fixed; position: fixed;
height: 100vh; height: 100vh;
width: 100vw; width: 100vw;

View File

@ -5,11 +5,11 @@ import Logo from '../Logo'
import { H2, P } from '../Text' import { H2, P } from '../Text'
import { InfoButton, OverlayWrapper, TopLeft } from './styles' import { InfoButton, OverlayWrapper, TopLeft } from './styles'
const VideoOverlay = ({ active, title, org, setInfoActive }) => ( const VideoOverlay = ({ active, title, org, setInfoActive, onClick }) => (
// const displayTitle = `${title}${org ? ` — ${org}` : ''}` // const displayTitle = `${title}${org ? ` — ${org}` : ''}`
<Fragment> <Fragment>
<OverlayWrapper> <OverlayWrapper onClick={onClick}>
<TopLeft $active={active}> <TopLeft $active={active}>
<Logo active={active} /> <Logo active={active} />
<P <P

View File

@ -7,7 +7,7 @@ export const OverlayWrapper = styled.div`
position: fixed; position: fixed;
height: 100vh; height: 100vh;
width: 100vw; width: 100vw;
pointer-events: none; /* pointer-events: none; */
` `
export const TopLeft = styled.div` export const TopLeft = styled.div`
opacity: 0; opacity: 0;

View File

@ -1,6 +1,6 @@
import { useEffect, useState, useRef } from 'preact/hooks' import { useEffect, useState, useRef } from 'preact/hooks'
import axios from 'axios' import axios from 'axios'
import ical from 'ical' import ICAL from 'ical.js'
import config from '../data/config' import config from '../data/config'
export const useEventStream = () => { export const useEventStream = () => {
@ -11,14 +11,24 @@ export const useEventStream = () => {
setLoading(true) setLoading(true)
const { data: responseData } = await axios.get(`${config.calendar}`) const { data: responseData } = await axios.get(`${config.calendar}`)
const calItems = Object.values(ical.parseICS(responseData)) const jCalData = ICAL.parse(responseData)
.filter(feedItem => feedItem.type === 'VEVENT') const comp = new ICAL.Component(jCalData)
.sort((a, b) => new Date(a.start) - new Date(b.start))
const vevents = comp.getAllSubcomponents('vevent')
const calEvents = vevents
.map(vevent => new ICAL.Event(vevent))
.sort((a, b) => a.startDate.toJSDate() - b.startDate.toJSDate())
await Promise.all( await Promise.all(
calItems.map(async calItem => { calEvents.map(async calItem => {
if (calItem.url) { const url = calItem.component.getAllProperties('url')[0]
const id = calItem.url.val.split('/').pop() if (url) {
console.log('url', url)
const id = url
.getFirstValue()
.split('/')
.pop()
const { const {
data: { data: {
account, account,
@ -31,11 +41,8 @@ export const useEventStream = () => {
views, views,
duration, duration,
}, },
data: nesd,
} = await axios.get(`https://tv.undersco.re/api/v1/videos/${id}`) } = await axios.get(`https://tv.undersco.re/api/v1/videos/${id}`)
console.log({ nesd })
const item = { const item = {
title: calItem.summary, title: calItem.summary,
account, account,
@ -47,11 +54,11 @@ export const useEventStream = () => {
state, state,
previewPath, previewPath,
views, views,
start: calItem.start, start: calItem.startDate.toJSDate(),
end: calItem.end, end: calItem.endDate.toJSDate(),
id, id,
duration, duration,
videoUrl: calItem?.url?.val, videoUrl: url.getFirstValue(),
} }
setData(arr => [...arr, item]) setData(arr => [...arr, item])
} }