replaced ical library
This commit is contained in:
parent
f1bd7697fa
commit
5630705ea1
@ -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
14
app.js
@ -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}
|
||||||
|
@ -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"
|
||||||
@ -35,4 +36,4 @@
|
|||||||
"sass": "^1.32.8",
|
"sass": "^1.32.8",
|
||||||
"scss": "^0.2.4"
|
"scss": "^0.2.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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,26 +37,40 @@ 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 {
|
||||||
|
player.play()
|
||||||
try {
|
} catch (error) {
|
||||||
player.play()
|
console.log({ error })
|
||||||
} catch (error) {
|
|
||||||
console.log({ error })
|
|
||||||
setOverlayActiveState(true)
|
|
||||||
setPlaying(false)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setOverlayActiveState(true)
|
setOverlayActiveState(true)
|
||||||
player.pause()
|
setPlaying(false)
|
||||||
}
|
}
|
||||||
}, [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,
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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])
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user